问题描述
找两个字符串的最长公共子串,这个子串要求在原字符串中是连续的。
而找两个字符串的最长公共子序列,只要求子序列的字符都在原字符串中出现且保持相对顺序不对
解决思路
动态规划
1.最长公共子串,
S1=a1a2a3..am
S2=b1b2b3..bn
状态转移方程
记f(i,j)是以a[i]和b[j]结尾的字符串的最长公共子串(要求a[i]==b[j],子串以a[i]结尾)
f(i,j)=⎧⎩⎨0f(i−1,j−1)+11i=0||j=0i,j>0andai=bjandai−1=bj−1i,j>0&&&ai=bjandai−1!=bj−1
那么最终的最长公共子串为 maxf[i][j]
2.最长公共子序列,
S1=a1a2a3..am
S2=b1b2b3..bn
状态转移方程
记f(i,j)是以a[i]和b[j]结尾相应长度的字符串的最长公共子序列(并不要求末尾字符相等)
f(i,j)=⎧⎩⎨0f(i−1,j−1)+1maxf(i,j−1),f(i−1,j)i=0||j=0i,j>0&&&ai=bjai!=bj
那么最终的最长公共子序列为
f[m][n]
如果没看懂直接看代码就懂了。。。
class Solution {
public:
string LCS(const string &a,const string &b) {
int m=a.size(),n=b.size();
vector<vector<string>> res(m+1,vector<string>(n+1));
if(m==0||n==0)return string("");
string best;
for(int i=1;i<=m;++i)
for(int j=1;j<=n;++j){
if(a[i-1]==b[j-1]){
string tmp;
tmp.push_back(a[i-1]);
if(i>1&&j>1&&a[i-2]==b[j-2])res[i][j]=res[i-1][j-1]+tmp;
else res[i][j]=tmp;
}
if(best.size()<res[i][j].size())best=res[i][j];
}
return best;
}
string LCS2(const string &a,const string &b) {
int m=a.size(),n=b.size();
vector<vector<string>> res(m+1,vector<string>(n+1));
if(m==0||n==0)return string("");
for(int i=1;i<=m;++i)
for(int j=1;j<=n;++j){
if(a[i-1]==b[j-1]){
string tmp;
tmp.push_back(a[i-1]);
res[i][j]=res[i-1][j-1]+tmp;
}
else {
if(res[i][j-1].size()<res[i-1][j].size())
res[i][j]=res[i-1][j];
else res[i][j]=res[i][j-1];
}
}
return res[m][n];
}
};
case0:
hellomygod子串1
hellogod子串2
hello最长公共子串
hellogod最长公共子序列