公共子序列有别于公共子串,子序列可以不连续,如 X = [abcbdab], Y = [bdcaba],则 bcba 为其一个公共最长子序列。同样考虑DP方案,假设 X = <x1, x2, ..., xm>, Y = <y1, y2, ..., yn> ,LCS(X, Y) 表示二者的公共最长子序列,则有
- 如果 xm == yn,则 LCS(X, Y) = xm + LCS(Xm-1, Yn-1);
- 如果 xm != yn,则 LCS(X, Y) = max{LCS(Xm-1, Y), LCS(X, Yn-1)};
于是LCS问题具有重叠子问题性质。
#include <iostream>
#include <vector>
#include <string>
using namespace std;
#define INF (~(1<<31))
int main(){
string s1, s2;
cin >> s1 >> s2;
int len1 = (int)s1.size(), len2 = (int)s2.size();
vector<vector<int>> mat(len1+1, vector<int>(len2+1, 0));
for(int i = 1; i <= len1; ++i){
for(int j = 1; j <= len2; ++j){
if(s1[i-1] == s2[j-1]){
mat[i][j] = mat[i-1][j-1] + 1;
}else if(mat[i-1][j] > mat[i][j-1]){
mat[i][j] = mat[i-1][j];
}else{
mat[i][j] = mat[i][j-1];
}
}
}
string outs;
int i = len1, j = len2;
while(i && j){
if(s1[i-1] == s2[j-1]){
outs = s1[i-1] + outs;
--i; --j;
}else if(mat[i-1][j] > mat[i][j-1]){
--i;
}else{
--j;
}
}
cout << mat[len1][len2] << ": " << outs;
return 0;
}