某高中oj b179: 空罐 Cans

来源:互联网 发布:装修淘宝店用什么软件 编辑:程序博客网 时间:2024/06/02 23:23

题目链接:http://zerojudge.tw/ShowProblem?problemid=b179

题目大意:一个基因可以分裂出四个子基因,这四个基因末尾增加a,b,c,或d,但本身的第一个碱基会失去,当基因长度为0时会死去,同时当基因含有制病片段时就会生病,问p天后有好多死去,好多生病。

题目思路:ac自动机dp,dp[i][j][k]表示第i天在结点k有多少长度为j的基因。对于基因变短,可以由fail指针转移。要分两种
情况讨论,长度小于结点深度和不小于结点深度。

#include<stdio.h>#include<stdlib.h>#include<string.h>#include<string>#include<queue>#include<algorithm>#include<vector>#include<stack>#include<list>#include<iostream>#include<map>using namespace std;#define inf 0x3f3f3f3f#define Max 110#define mod 10007int max(int a,int b){return a>b?a:b;}int min(int a,int b){return a<b?a:b;}struct node{    int cnt,fail,dep;    int next[4];    void init()    {        cnt=fail=dep=0;        memset(next,0,sizeof(next));    }}tri[1600];char s[1000],str[1000];int dp[330][110][1600],q[1600];int cnt;void insert(char *s){    int i,p,x;    p=0;    for(i=0;s[i];i++)    {        x=s[i]-'a';        if(!tri[p].next[x])        {            tri[++cnt].init();            tri[cnt].dep=tri[p].dep+1;            tri[p].next[x]=cnt;        }        p=tri[p].next[x];    }    tri[p].cnt++;}void bfs(){    int i,p,head,tail,suf;    p=head=tail=0;    for(i=0;i<4;i++)    {        if(tri[0].next[i])        {            q[tail++]=tri[0].next[i];            tri[q[tail-1]].fail=0;        }    }    while(head<tail)    {        p=q[head++],suf=tri[p].fail;        tri[p].cnt+=tri[suf].cnt;        for(i=0;i<4;i++)        {            if(tri[p].next[i])            {                q[tail++]=tri[p].next[i];                tri[q[tail-1]].fail=tri[suf].next[i];            }            else                tri[p].next[i]=tri[suf].next[i];        }    }}void solve(char *s,int n){    int i,j,k,g,p,x,pos;    int len=strlen(s);    p=0;    for(i=0;i<=n;i++)    for(j=0;j<=100&&j<=n+len;j++)    for(k=0;k<=cnt;k++)        dp[i][j][k]=0;    for(i=0;s[i];i++)    {        x=s[i]-'a';        p=tri[p].next[x];        if(tri[p].cnt)        {            printf("0 1\n");            return;        }    }    dp[0][len][p]=1;    for(i=0;i<n;i++)    for(j=1;j<=100&&j<=n+len;j++)    for(k=0;k<=cnt;k++)    {        if(dp[i][j][k]==0||tri[k].cnt) continue;        for(g=0;g<4;g++)        {            pos=tri[k].next[g];            dp[i+1][j+1][pos]+=dp[i][j][k];            dp[i+1][j+1][pos]%=mod;        }        if(j-1<tri[k].dep)        {            pos=tri[k].fail;            dp[i+1][j-1][pos]+=dp[i][j][k];            dp[i+1][j-1][pos]%=mod;        }        else        {            dp[i+1][j-1][k]+=dp[i][j][k];            dp[i+1][j-1][k]%=mod;        }    }    int ans1=0,ans2=0;    for(i=1;i<=n;i++)        ans1=(ans1+dp[i][0][0])%mod;    for(i=1;i<=n;i++)    for(j=0;j<=100&&j<=n+len;j++)    for(k=0;k<=cnt;k++)    {     //   printf("i %d j %d k %d dp %d\n",i,j,k,dp[i][j][k]);        if(tri[k].cnt)        ans2=(ans2+dp[i][j][k])%mod;    }    printf("%d %d\n",ans1,ans2);}int main(){    int p,n,i,j;    while(scanf("%s",s)!=EOF)    {        scanf("%d%d",&p,&n);        cnt=0;        tri[0].init();        while(n--)        {            scanf("%s",str);            insert(str);        }        bfs();        solve(s,p);    }}


 

 

原创粉丝点击