首先不要混淆了这两个问题:最长公共子序列(Longest Common Subsequence)和最长公共子串(Longest Common Substring)。不同于子串,子序列不需要在原序列中占用连续的位置。
最长公共子序列
dp[i][j]
表示在 s1
中前 i
个字符组成的字符串,和在 s2
中前 j
个字符组成的字符串,它们两个的最长公共子序列的长度。
1 2 3 4 5 6 7 8 9 10 11 12 13 14
| int LongestCommonSequence(String s1, String s2) { int[][] dp = new int[s1.length() + 1][s2.length() + 1]; for (int i = 0; i <= s1.length(); i++) { for (int j = 0; j <= s2.length(); j++) { if (i == 0 || j == 0) { dp[i][j] = 0; continue; } if (s1.charAt(i - 1) == s2.charAt(j - 1)) dp[i][j] = dp[i - 1][j - 1] + 1; else dp[i][j] = Math.max(dp[i][j - 1], dp[i - 1][j]); } } return dp[s1.length()][s2.length()]; }
|
最长公共子串
dp[i][j]
表示在 s1
中前 i
个字符组成的字符串,和在 s2
中前 j
个字符组成的字符串,它们两个的最长公共子串的长度,并且满足该字串的末尾是 s1[i] == s2[j]
。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
| int LongestCommonSubstring(String s1, String s2) { int[][] dp = new int[s1.length() + 1][s2.length() + 1]; int ans = 0; for (int i = 0; i <= s1.length(); i++) { for (int j = 0; j <= s2.length(); j++) { if (i == 0 || j == 0) { dp[i][j] = 0; continue; } if (s1.charAt(i - 1) == s2.charAt(j - 1)) { dp[i][j] = dp[i - 1][j - 1] + 1; } else { dp[i][j] = 0; } ans = Math.max(ans, dp[i][j]); } } return ans; }
|