2020-5 leetcode 1092. 最短公共超序列

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;
    }
};
  • 1
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值