bzoj 2423: [HAOI2010]最长公共子序列dp+计数

Posted lokiii

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了bzoj 2423: [HAOI2010]最长公共子序列dp+计数相关的知识,希望对你有一定的参考价值。

设f[i][j]为a序列前i个字符和b序列前j个字符的最长公共子序列,转移很好说就是f[i][j]=max(f[i-1][j],f[i][j-1],f[i-1][j-1]+(a[i]==b[j]))
设g[i][j]为a序列前i个字符和b序列前j个字符的最长公共子序列个数,这个转移是转移f的时候从前驱状态长度相同的加起来即可
要滚动数组

#include<iostream>
#include<cstdio>
#include<cstring>
using namespace std;
const int N=5005,mod=100000000;
int n,m,f[2][N],g[2][N];
char a[N],b[N];
int main()
{
    scanf("%s%s",a+1,b+1);
    n=strlen(a+1)-1,m=strlen(b+1)-1;
    for(int i=0;i<=m;i++) 
        g[0][i]=1;
    g[1][0]=1;
    for(int i=1;i<=n;i++)
        for(int j=1;j<=m;j++)
        {
            if(a[i]==b[j])
            {
                f[i&1][j]=f[~i&1][j-1]+1;
                g[i&1][j]=g[~i&1][j-1];
                if(f[i&1][j]==f[~i&1][j])
                    g[i&1][j]=(g[i&1][j]+g[~i&1][j])%mod;
                if(f[i&1][j]==f[i&1][j-1])
                    g[i&1][j]=(g[i&1][j]+g[i&1][j-1])%mod;
            }
            else
            {
                f[i&1][j]=max(f[~i&1][j],f[i&1][j-1]);
                g[i&1][j]=0;
                if(f[i&1][j]==f[~i&1][j-1])
                    g[i&1][j]=((g[i&1][j]-g[~i&1][j-1])%mod+mod)%mod;
                if(f[i&1][j]==f[~i&1][j])
                    g[i&1][j]=(g[i&1][j]+g[~i&1][j])%mod;
                if(f[i&1][j]==f[i&1][j-1])
                    g[i&1][j]=(g[i&1][j]+g[i&1][j-1])%mod;
            }
        }
    printf("%d
%d
",f[n&1][m],g[n&1][m]);
    return 0;
}


以上是关于bzoj 2423: [HAOI2010]最长公共子序列dp+计数的主要内容,如果未能解决你的问题,请参考以下文章

bzoj2423: [HAOI2010]最长公共子序列

bzoj 2423: [HAOI2010]最长公共子序列dp+计数

bzoj2423[HAOI2010]最长公共子序列 dp

BZOJ 2423: [HAOI2010]最长公共子序列|动态规划

HAOI2010 最长公共子序列

COGS 445. [HAOI2010]最长公共子序列