NOIP 2015 子串

来源:互联网 发布:好听的淘宝童装店名 编辑:程序博客网 时间:2024/06/05 09:14

评测传送

一开始做就想暴力,蒟蒻的dp实在是太弱了。

言归正传。
我们用f[i][j][p][0/1]表示用了a串前 i 个字符作为p段,匹配了b串前 j 个字符(0表示第i个字符没有用,1表示第i个字符用了)。
那么有

f[i][j][p][0]=f[i1][j][p][1]+f[i1][j][p][1]

f[i][j][p][1]=f[i1][j1][p1][1]+f[i1][j1][p1][0]+f[i1][j1][p][1],(a[i]==b[j])

解释一下第二个式子:
f[i-1][j-1][p][1]+f[i-1][j-1][p-1][1]表示i和前面的第i-1不拼成一串单独作为1串。
f[i-1][j-1][p][1]表示和第i-1合成一串。
数组开不下,因为每次只用到f[i-1],所以用滚动数组就可以了。

#include<iostream>#include<cstdio>#include<cstring>#include<algorithm>#include<ctime>#include<queue>#define LL long longusing namespace std;const int MOD=1000000007;LL f[3][209][209][3];int n,m,k;char a[1009],b[309];LL ans;int main(){    freopen("substring.in","r",stdin);    scanf("%d%d%d\n",&n,&m,&k);    gets(a+1);gets(b+1);    f[0][0][0][0]=1;     int now=1;    for(int i=1;i<=n;i++)    {        f[now][0][0][0]=1;        for(int j=1;j<=m;j++)        {            for(int p=1;p<=k;p++)            {                f[now][j][p][0]=f[now][j][p][1]=0;//先将上上次的清空                f[now][j][p][0]=(f[now^1][j][p][0]+f[now^1][j][p][1])%MOD;                if(a[i]==b[j])                f[now][j][p][1]=(f[now^1][j-1][p-1][1]+f[now^1][j-1][p-1][0]+f[now^1][j-1][p][1])%MOD;            }        }        now=now^1;    }    ans=(f[now^1][m][k][1]+f[now^1][m][k][0])%MOD;    printf("%lld",ans);}
原创粉丝点击