最长公共子串
动态规划法:
- 定义字符串str1的索引为i, 第二个字符串str2的索引为j
- 定义dp[i][j] 为str1取前面长度为i的子串,str2取前面长度为j的子串,str1必须以第i个结果,str2必须以第j个结果
- 定义状态转移方程
原理:如果2个字符串的最后一个不相等,它们的LCS=空串, 若相等,2个都往前推一位,该情况的子串+这一位=现在的子串
特别注意:比如对于str1, 前i个: 索引是从0到i - 1
-
java实现
public int longestCommonSubstring(String A, String B) { int a_len = A.length(); int b_len = B.length(); int max = 0; //dp[i][j] 为 A取前i个,B取前j个,看这两个的LCS长度,各个的最后一个不等,肯定是0了 int[][] dp = new int[a_len + 1][b_len + 1]; for (int i = 1; i <= a_len; ++i) { for (int j = 1; j <= b_len; ++j) { if (A.charAt(i - 1) == B.charAt(j - 1)) { dp[i][j] = dp[i - 1][j - 1] + 1; if (dp[i][j] > max) max = dp[i][j]; } else { dp[i][j] = 0; } } } return max; }
最长公共子序列
和最长公共子串的区别: 这个可以跳,当str1[i -1] != str2[j - 1]时,dp[i][j]可以从2个方向来,dp[i - 1][j] 或 dp[i][j - 1]
dp[i][j] >= dp[<=i][<=j] 所以最近的就是dp[i - 1][j] 和 dp[i][j - 1]
public int longestCommonSubsequence(String A, String B) {
int a_len = A.length();
int b_len = B.length();
int max = 0;
int[][] dp = new int[a_len + 1][b_len + 1];
for (int i = 1; i <= a_len; i++) {
for (int j = 1; j <= b_len; j++) {
if (A.charAt(i - 1) == B.charAt(j - 1)) {
dp[i][j] = dp[i - 1][j - 1] + 1;
} else {
//区别在这里
dp[i][j] = Math.max(dp[i - 1][j], dp[i][j - 1]);
}
max = Math.max(max, dp[i][j]);
}
}
return max;
}