LCS

Posted kayiko

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了LCS相关的知识,希望对你有一定的参考价值。

做了几道LCS的题,总结一下

UVA10723

技术图片
#include <cstdio>
#include<iostream>
#include<iomanip>
#include<cstring>
#include<sstream>
#include<algorithm>
#include<cstdio>
#include<stdlib.h>
#include<string>
#include<map>
#define _for(i,a,b) for(int i=a;i<=b;i++)
using namespace std;
typedef long long ll;
const int MAXN=1e6+10;
const int mod=998244353;
const int INF=0x3f3f3f3f;
char a[1010],b[1010];
int dp[1010][1010];
ll cnt[1000][1000];
int main()
{
    int t;
    int dd=1;
    scanf("%d",&t);
    getchar();
    while(t--)
    {
        gets(a);
        gets(b);
        int len1=strlen(a);
        int len2=strlen(b);
        memset(dp,0,sizeof(dp));
            memset(cnt,0,sizeof(cnt));
        for(int i=0;i<=len1;i++)cnt[i][0]=1;
        for(int i=0;i<=len2;i++)cnt[0][i]=1;
        for(int i=1;i<=len1;i++)
        {
            for(int j=1;j<=len2;j++)
            {
                if(a[i-1]==b[j-1])
                {
                    dp[i][j]=dp[i-1][j-1]+1;
                    cnt[i][j]=cnt[i-1][j-1];
                }
                else
                {
                    if(dp[i-1][j]>dp[i][j-1])
                    {
                        dp[i][j]=dp[i-1][j];
                        cnt[i][j]=cnt[i-1][j];
                    }
                    else if(dp[i-1][j]<dp[i][j-1])
                    {
                        dp[i][j]=dp[i][j-1];
                        cnt[i][j]=cnt[i][j-1];
                    }
                    else
                    {
                        dp[i][j]=dp[i-1][j];
                        cnt[i][j]=cnt[i-1][j]+cnt[i][j-1];
                    }
                }
            }
        }
        printf("Case #%d: %d %lld
",dd++,len1+len2-dp[len1][len2],cnt[len1][len2]);
    }
}
View Code

求全部两个串的全部的LCS

技术图片
#include <iostream>
#include <string>
#include <vector>
#include <set>
#include <algorithm>
using namespace std;

string X = "ABCBDAB";
string Y = "BDCABA";
vector<vector<int>> table; // 动态规划表
set<string> setOfLCS;      // set保存所有的LCS

int max(int a, int b)
{
    return (a>b)? a:b;
}

/**
 * 构造表,并返回X和Y的LCS的长度
 */
int lcs(int m, int n)
{
    // 表的大小为(m+1)*(n+1)
    table = vector<vector<int>>(m+1,vector<int>(n+1));

    for(int i=0; i<m+1; ++i)
    {
        for(int j=0; j<n+1; ++j)
        {
            // 第一行和第一列置0
            if (i == 0 || j == 0)
                table[i][j] = 0;
            else if(X[i-1] == Y[j-1])
                table[i][j] = table[i-1][j-1] + 1;
            else
                table[i][j] = max(table[i-1][j], table[i][j-1]);
        }
    }

    return table[m][n];
}

/**
 * 求出所有的最长公共子序列,并放入set中
 */
void traceBack(int i, int j, string lcs_str, int lcs_len)
{
    while (i>0 && j>0)
    {
        if (X[i-1] == Y[j-1])
        {
            lcs_str.push_back(X[i-1]);
            --i;
            --j;
        }
        else
        {
            if (table[i-1][j] > table[i][j-1])
                --i;
            else if (table[i-1][j] < table[i][j-1])
                --j;
            else   // 相等的情况
            {
                traceBack(i-1, j, lcs_str, lcs_len);
                traceBack(i, j-1, lcs_str, lcs_len);
                return;
            }
        }
    }

    string str(lcs_str.rbegin(), lcs_str.rend()); // lcs_str逆序
        if((int)str.size() == lcs_len)                // 判断str的长度是否等于lcs_len
            setOfLCS.insert(str);
}

void print()
{
    set<string>::iterator beg = setOfLCS.begin();
    for( ; beg!=setOfLCS.end(); ++beg)
        cout << *beg << endl;
}
int main()
{
    int m = X.length();
    int n = Y.length();
    int length = lcs(m, n);
    cout << "The length of LCS is " << length << endl;

    string str;
    traceBack(m, n, str, length);
    print();

    getchar();
    return 0;
View Code

最长公共子序列

TLE的

技术图片
#include <cstdio>
#include<iostream>
#include<iomanip>
#include<cstring>
#include<sstream>
#include<algorithm>
#include<cstdio>
#include<stdlib.h>
#include<string>
#include<map>
#define _for(i,a,b) for(int i=a;i<=b;i++)
using namespace std;
typedef long long ll;
const int MAXN=1e6+10;
const int mod=1e8;
const int INF=0x3f3f3f3f;
int dp[6000][6000];//ABAAXGF AABXFGA
int cnt[6000][6000];
int g[6000][6000];
char a[6000],b[6000];
int main()
{
    scanf("%s%s",a,b);
    int len1=strlen(a);
    int len2=strlen(b);
    len1--,len2--;
    for(int i=0;i<=len1;i++)cnt[i][0]=1,g[i][0]=1;
    for(int i=0;i<=len2;i++)cnt[0][i]=1,g[0][i]=1;
    for(int i=1;i<=len1;i++)
    {
        for(int j=1;j<=len2;j++)
        {
            if(a[i-1]==b[j-1])
                dp[i][j]=dp[i-1][j-1]+1,cnt[i][j]=cnt[i-1][j-1];
            else
            {
                if(dp[i-1][j]>dp[i][j-1])
                {
                    dp[i][j]=dp[i-1][j],cnt[i][j]=cnt[i-1][j];
                }
                else if(dp[i-1][j]<dp[i][j-1])
                {
                    dp[i][j]=dp[i][j-1],cnt[i][j]=cnt[i][j-1];
                }
                else
                {
                    dp[i][j]=dp[i-1][j],cnt[i][j]=cnt[i-1][j]+cnt[i][j-1];
                }
            }
            if(dp[i][j]==dp[i-1][j])
                (g[i][j]+=g[i-1][j])%mod;
            if(dp[i][j]==dp[i][j-1])
                (g[i][j]+=g[i][j-1])%mod;
            if(a[i]==b[j])
                if(dp[i][j]==dp[i-1][j-1]+1)(g[i][j]+=g[i-1][j-1])%mod;
            else if(dp[i][j]==dp[i-1][j-1])(g[i][j]-=g[i-1][j-1])%mod;

        }
    }
    cout<<dp[len1][len2]<<endl;
    cout<<g[len1][len2]%mod<<endl;
}
View Code

AC的

技术图片
#include <cstdio>
#include<iostream>
#include<iomanip>
#include<cstring>
#include<sstream>
#include<algorithm>
#include<cstdio>
#include<stdlib.h>
#include<string>
#include<map>
#define _for(i,a,b) for(int i=a;i<=b;i++)
using namespace std;
//typedef long long ll;
int f[5005],last[5005],num[5005],ll[5005];
char s1[5005],s2[5005];
int mod=100000000;
int n1,n2;
int main()
{
    int i,j,ans,bj,kl;
    scanf("%s",s1);scanf("%s",s2);
    n1=strlen(s1);n2=strlen(s2);
    n1--;n2--;
    for(i=0;i<=n2;i++)ll[i]=1;
    for(i=0;i<n1;i++){
        for(j=0;j<n2;j++){
            ll[0]=1;num[0]=1;
            if(s1[i]==s2[j]){
                f[j+1]=last[j]+1;num[j+1]=ll[j];
                num[j]=num[j]%mod;
                if(last[j+1]==f[j+1])num[j+1]+=ll[j+1];
                num[j]=num[j]%mod;
                if(f[j]==f[j+1])num[j+1]+=num[j];
                num[j]=num[j]%mod;
            }
            else {
                if(f[j]>last[j+1]){
                    f[j+1]=f[j];num[j+1]=num[j];
                    num[j]=num[j]%mod;
                }
                else if(f[j]<last[j+1]){
                    f[j+1]=last[j+1];num[j+1]=ll[j+1];
                    num[j]=num[j]%mod;
                }
                else {
                    f[j+1]=f[j];
                    num[j+1]=num[j]+ll[j+1];
                    if(last[j]==f[j+1])num[j+1]-=ll[j];
                    num[j]=num[j]%mod;
                }
            }
            num[j]=num[j]%mod;
        }
        for(j=0;j<n2;j++){last[j+1]=f[j+1];ll[j+1]=num[j+1];}
    }
    printf("%d
%d",f[n2],num[n2]);
    return 0;
}
View Code

以上是关于LCS的主要内容,如果未能解决你的问题,请参考以下文章

最长公共子序列(LCS),求LCS长度和打印输出LCS

LCS的数量

经典问题LCS(最大公共子串问题)C代码实现

LCS问题

Aizu2090LCS

已知一序列无重复元素,对LCS通过LIS进行优化