因此,最长公共子序列问题的psuedocode如下所示。
最长公共子序列(s1,s2):
如果字符串以同一个字母c开头,则返回的结果是c
加上其余s1和s2之间的最长公共子序列
(也就是说,s1和s2没有第一个字母)。例如
“hollo”和“hello”之间的最长子序列是“h”加上
在“ollow”和“ello”之间找到的最长子序列。
否则,如果
字符串不以同一个字母开头,返回
以下两个:s1和
S2的其余部分(S2不带第一个字母),最长的公共
s1的其余部分(s1不带第一个字母)与
第2页。例如,最长的公共子序列(“ollow”,“ello”)是
最长公共子序列(“ollow”,“llo”)中较长的一个,以及
最长公共子序列(“llow”、“ello”)。
我没有得到的部分是,当字符串不是以同一个字母开头时,为什么要取(s1没有第一个字母,s2),(s1,s2没有第一个字母)当这些步骤不匹配时,我们为什么要递归地进行这些步骤只是一个很难理解的集合算法吗?这背后的原因是什么?
最佳答案
虽然@yash mahajan已经涵盖了所有内容,但我将提供另一种思考方法。
穿过两个字符串,假设你在字符串A的位置i(长度m)和字符串B的位置j(长度n)。
一。如果两个字符串的当前两个字符相同:
最长公共子序列=子串A[0…i-1]和子串B[0…j-1]+1之间的最长公共子序列。
2.如果两个字符不同:
最长公共子序列=Max(子串A[0…i-1]和字符串B之间的最长公共子序列,字符串A和子串B[0…j-1]之间的最长公共子序列)
如果你读了密码,你会有一个更清楚的想法。
public class Solution {
public int longestCommonSubsequence(String A, String B) {
if(A == null || B == null || A.length() == 0 || B.length() == 0) {
return 0;
}
int m = A.length();
int n = B.length();
int[][] commonSubsequenceLength = new int[m + 1][n + 1];
for(int i = 1; i <= m; i++) {
for(int j = 1; j <= n; j++) {
if(A.charAt(i - 1) == B.charAt(j - 1)) {
commonSubsequenceLength[i][j] = commonSubsequenceLength[i - 1][j - 1] + 1;
} else {
commonSubsequenceLength[i][j] = Math.max(commonSubsequenceLength[i][j - 1], commonSubsequenceLength[i - 1][j]);
}
}
}
return commonSubsequenceLength[m][n];
}
}