定义
longest common subsequence:给定两个序列S1和S2,求二者公共子序列S3的最长的长度。
//注意不是最大公共子串
分析
这个问题可以按照序列的长度来划分状态,也就是S1的前i个字符和S2的前j个字符的最长公共子序列长度,记为lcs[i][j]。
如果S1的第i项,和S2的第j项相同,那么S1[i]与S2[j]作为公共子序列的末尾,则
lcs[i][j] = lcs [ i-1 ] [ j-1 ]+1
也可以不让S1[i]与S2[j]作为公共子序列的末尾,则
lcs[i][j] = max(lcs[ i ] [ j -1 ], lcs[ i-1 ] [ j ])
注意:这种方法考虑的是到某一位(i, j)为止,而不一定是以它结尾
关于不相等的转移方程:可以这么理解:既然两个位置不等,那么就求这两个位置之前的一个最大值,而显然,越靠近这两个位置的值越大,那么就取各自减1的位置就行了。
这个不相等时的转移方程是一定要有的,因为不像最大公共子串维护了一个最大值,一旦不相等了不需要看前面的累计,不需要任何处理,继续往下走就行;这里是求子序列,序列是可以不连续的,所以必须每个点都要存值。
int dp[10][10];
int main(){
string a, b;
cin >> a >> b;
int lena = a.length();
int lenb = b.length();
for(int i = 0; i < lena; i++){
for(int j = 0; j < lenb; j++){
if(a[i] == b[j])
dp[i+1][j+1] = dp[i][j] + 1;
else
dp[i+1][j+1] = max(dp[i][j+1], dp[i+1][j]);
}
}
//输出dp数组,最后一个值即为答案
for(int i = 1; i < lena+1; i++){
for(int j = 1; j < lenb+1; j++)
cout << dp[i][j] << " ";
cout << endl;
}
return 0;
}