• 问题 G: 最长公共子串问题


     

    希腊有一个著名的历史学家,他为了专心写一本史学巨著,而把自己关在一个高塔之上。有一天,他目睹了一场凶杀案的发生,但事后,他惊讶地发现所有围观人的证词都不一样,甚至有的完全相反。于是,他放弃了继续写作的念头。他说:“人们连发生在眼前的事实都分辨不清,我又怎么知道我写的历史是真是假呢?”

    虽然历史的真假我们很难辨别,但文章是否抄袭,我们还是可以用所谓的LCS算法解决的。

    给出两个字符串S1和S2,我们现在希望了解两个字符串之间的“相似度”。这个相似度是这样定义的:找出第三个字符串S3,组成S3的元素也出现在S1和S2中,而且这些元素必须是以相同的顺序出现,但不必要是连续的。能找到的S3越长则S1和S2就越相似。相似度即是这个S3的长度。例如,当S1="abcde",S2="dabfda",S3就是"abd", S1和S2的相似度就是3。

    输入

    第一行为一个整数,表示第一个字符串的长度。

    第二行为第一个字符串。

    第三行为一个整数,表示第二个字符串的长度。

    第二行为第二个字符串。

    输出

    一个整数,即两个字符串的相似度。

    样例输入 Copy

    5
    abccb
    5
    acabc

    样例输出 Copy

    3
    #include<cstdio>
    #include<iostream>
    #include<algorithm>
    #include<map> 
    #include<bits/stdc++.h> 
    using namespace std;
    typedef long long ll; 
    inline int read()
    {
        int x=0,f=1;char ch=getchar();
        while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
        while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}
        return x*f;
    }
    const int INF=0x3f3f3f3f;
    const int maxn=5e3;
    int n,m;
    string str1,str2;
    int dp[maxn][maxn];
    void inint(){
        cin>>n;
        cin>>str1;
        cin>>m;
        cin>>str2; 
    }
    int main(){
        inint();
        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]);
                }
            }
        }
        printf("%d",dp[n][m]); 
    }

     输出方案:

    #include<cstdio>
    #include<iostream>
    #include<algorithm>
    #include<map> 
    #include<bits/stdc++.h> 
    using namespace std;
    typedef long long ll; 
    inline int read()
    {
        int x=0,f=1;char ch=getchar();
        while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
        while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}
        return x*f;
    }
    const int INF=0x3f3f3f3f;
    const int maxn=5e3;
    int n,m;
    string str1,str2;
    int dp[maxn][maxn];
    char ans[maxn];
    void inint(){
        cin>>n;
        cin>>str1;
        cin>>m;
        cin>>str2; 
    }
    int main(){
        inint();
        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]);
                }
            }
        }
        for(int i=1;i<=n;i++){
            for(int j=1;j<=m;j++){
                cout<<dp[i][j]<<" ";
            }
            cout<<endl;
        }
        int l=n,r=m;
        int p=0;
        while(l>0&&r>0){
            if(str1[l-1]==str2[r-1]){
                ans[p++]=str1[l-1];
                l--;
                r--;
            }
            else if(dp[l][r-1]>dp[l-1][r]){
                r--;
            }
            else{
                l--;
            }
        }
        cout<<endl;
        printf("%d
    ",dp[n][m]); 
        for(int i=p-1;i>=0;i--){
            cout<<ans[i];
        }
    }
    #include<cstdio>
    #include<iostream>
    #include<algorithm>
    #include<map> 
    #include<bits/stdc++.h> 
    using namespace std;
    typedef long long ll; 
    inline int read()
    {
        int x=0,f=1;char ch=getchar();
        while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
        while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}
        return x*f;
    }
    const int INF=0x3f3f3f3f;
    const int maxn=5e3;
    int n,m;
    string str1,str2;
    int dp[maxn][maxn];
    char ans[maxn];
    void inint(){
        cin>>n;
        cin>>str1;
        cin>>m;
        cin>>str2; 
    }
    int main(){
        inint();
        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]);
                }
            }
        }
        for(int i=1;i<=n;i++){
            for(int j=1;j<=m;j++){
                cout<<dp[i][j]<<" ";
            }
            cout<<endl;
        }
        int l=n,r=m;
        int p=0;
        while(l>0&&r>0){
            if(str1[l-1]==str2[r-1]){
                ans[p++]=str1[l-1];
                l--;
                r--;
            }
            else if(dp[l][r-1]>dp[l-1][r]){
                r--;
            }
            else{
                l--;
            }
        }
        cout<<endl;
        printf("%d
    ",dp[n][m]); 
        for(int i=p-1;i>=0;i--){
            cout<<ans[i];
        }
    }
  • 相关阅读:
    力扣(LeetCode)验证回文字符串II 个人题解
    力扣(LeetCode)寻找数组的中心索引 个人题解
    力扣(LeetCode)验证回文串 个人题解
    力扣(LeetCode)三个数的最大乘积 个人题解
    力扣(LeetCode)二进制求和 个人题解
    力扣(LeetCode)加一 个人题解
    力扣(LeetCode)整数反转 个人题解
    力扣(LeetCode)颠倒二进制位 个人题解
    力扣(LeetCode)最后一个单词的长度 个人题解
    力扣(LeetCode)学生出勤记录I 个人题解
  • 原文地址:https://www.cnblogs.com/lipu123/p/12337903.html
Copyright © 2020-2023  润新知