最长公共子序列
题目描述
给定两个字符串str1和str2,输出两个字符串的最长公共子序列。如果最长公共子序列为空,则返回"-1"。目前给出的数据,仅仅会存在一个最长的公共子序列
示例1
输入:
"1A2C3D4B56","B1D23A456A"
返回值:
"123456"
示例2
输入:
"abc","def"
返回值:
"-1"
题目分析
动态方程:
if(s1[i-1] == s2[j-1])
dp[i][j] = dp[i-1][j-1] + 1;
else
dp[i][j] = max(dp[i-1][j], dp[i][j-1]);
填表
1 | A | 2 | C | 3 | D | 4 | B | 5 | 6 | ||
---|---|---|---|---|---|---|---|---|---|---|---|
0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | |
B | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 1 | 1 | 1 |
1 | 0 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 |
D | 0 | 1 | 1 | 1 | 1 | 1 | 2 | 2 | 2 | 2 | 2 |
2 | 0 | 1 | 1 | 2 | 2 | 2 | 2 | 2 | 2 | 2 | 2 |
3 | 0 | 1 | 1 | 2 | 2 | 3 | 3 | 3 | 3 | 3 | 3 |
A | 0 | 1 | 2 | 2 | 2 | 3 | 3 | 3 | 3 | 3 | 3 |
4 | 0 | 1 | 2 | 2 | 2 | 3 | 3 | 4 | 4 | 4 | 4 |
5 | 0 | 1 | 2 | 2 | 2 | 3 | 3 | 4 | 4 | 5 | 5 |
6 | 0 | 1 | 2 | 2 | 2 | 3 | 3 | 4 | 4 | 5 | 6 |
A | 0 | 1 | 2 | 2 | 2 | 3 | 3 | 4 | 4 | 5 | 6 |
代码
class Solution {
public:
/**
* longest common subsequence
* @param s1 string字符串 the string
* @param s2 string字符串 the string
* @return string字符串
*/
string LCS(string s1, string s2) {
// write code here
int ls1 = s1.size();
int ls2 = s2.size();
if(ls1==0 || ls2==0) return "-1";
int dp[ls1+1][ls2+1];
int m = ls1>ls2 ? ls1:ls2;
for(int i=0; i<=m; i++){
if(i<=ls1) dp[i][0] = 0;
if(i<=ls2) dp[0][i] = 0;
}
for(int i=1; i<=ls1; i++){
for(int j=1; j<=ls2; j++){
if(s1[i-1] == s2[j-1]){
dp[i][j] = dp[i-1][j-1] + 1;
}else{
dp[i][j] = max(dp[i-1][j], dp[i][j-1]);
}
}
}
int mx = 0;
string res = "";
int i=ls1,j=ls2;
while(i>0&&j>0){
if(s1[i-1]==s2[j-1]){ //对应dp[i][j] = dp[i-1][j-1] +1;的反推
res = s1[i-1]+res;
i--;
j--;
}else{ //对应dp[i][j] = max(dp[i-1][j],dp[i][j-1]);的反推
if(dp[i-1][j] < dp[i][j-1]){
j--;
}else if(dp[i-1][j] > dp[i][j-1]){
i--;
}else if(dp[i-1][j] == dp[i][j-1]){
j--;
}
}
}
return res=="" ? "-1":res;
}
};