1.方法1:动态规划,对于每个 i j 1,为了省空间,可以翻滚处理数组的行
2.先找出来最长的公共子序列是存在于哪里,然后哪个最长不就代表答案最短吗。两个维护的东西都用动态规划来处理。
class Solution {
public:
string shortestCommonSupersequence(string str1, string str2) {
vector<vector<int>> d(2,vector<int>(str2.size()+1,0));
vector<vector<string>> s(2,vector<string>(str2.size()+1,""));
for(int i=0;i<=str1.size();i++){
for(int j=0;j<=str2.size();j++){
if(i==0||j==0){
d[i&1][j]=0;
if(i) s[i&1][j]=str1.substr(0,i);
if(j) s[i&1][j]=str2.substr(0,j);
}
else{
int a=d[(i-1)&1][j];
int b=d[i&1][j-1];
if(a<=b){
d[i&1][j]=b;
s[i&1][j]=s[i&1][j-1]+str2[j-1];
}
else{
d[i&1][j]=a;
s[i&1][j]=s[(i-1)&1][j]+str1[i-1];
}
if(str1[i-1]==str2[j-1]){
if(d[i&1][j]<d[(i-1)&1][j-1]+1){
d[i&1][j]=d[(i-1)&1][j-1]+1;
s[i&1][j]=s[(i-1)&1][j-1]+str2[j-1];
}
}
}
}
}
return s[str1.size()&1][str2.size()];
}
};
方法2:1.先弄出最长公共子序列的长度,然后依据这个反推出最长公共子序列。
2.依据这个最长公共子序列来构造答案。(扣掉公共的不就只剩下各自的了吗)
#include<algorithm>
class Solution {
public:
string shortestCommonSupersequence(string str1, string str2) {
int n=str1.size(),m=str2.size();
vector<vector<int>> dp(n+1,vector<int>(m+1,0));
for(int i=1;i<=n;i++){
for(int j=1;j<=m;j++){
if(str1[i-1]==str2[j-1]){
dp[i][j]=dp[i-1][j-1]+1;
}
else{
dp[i][j]=max(dp[i-1][j],dp[i][j-1]);
}
}
}
string lcs="";
int i=n,j=m;
while(i>0&&j>0){
if(str1[i-1]==str2[j-1]){
lcs+=str2[j-1];
--i;
--j;
}
else{
dp[i-1][j]>dp[i][j-1]?--i:--j;
}
}
reverse(lcs.begin(),lcs.end());
string ans="";
i=0,j=0;
for(auto x:lcs){
while(x!=str1[i]) ans+=str1[i++];
while(x!=str2[j]) ans+=str2[j++];
ans+=x;
i++;
j++;
}
ans+=str1.substr(i);
ans+=str2.substr(j);
return ans;
}
};