hdu 4057 Rescue the Rabbit

来源:互联网 发布:网络大电影预算表图 编辑:程序博客网 时间:2024/05/18 15:04

ac自动机的状压dp

dp[i][j][k]表示长度为i,包含字符串的状态为j,自动机的状态为k是否可行。

#include <iostream>#include <cstdio>#include <cstring>#include <queue>using namespace std;const int root=0,N=4;int n,m;bool dp[2][1111][1111];int c[1111][10],a[111];int lon;struct{    int next[5],tmp,fail;}trie[1111];void trieini(){    memset(trie,0,sizeof(trie));    lon=0;}void insert(char s[],int h){    int t=root;    int n=strlen(s+1);    for(int i=1;i<=n;i++)    {        if(trie[t].next[s[i]-'A']==0)        trie[t].next[s[i]-'A']=++lon;        t=trie[t].next[s[i]-'A'];        if(i==n)        trie[t].tmp=1<<h-1;    }}void getfail(){    queue <int> q;    q.push(root);    while(!q.empty())    {        int t=q.front();        q.pop();        for(int i=0;i<N;i++)        if(trie[t].next[i])        {            int u=trie[t].next[i];            int tmp=trie[t].fail;            while(tmp!=root&&trie[tmp].next[i]==0)            tmp=trie[tmp].fail;            trie[u].fail=trie[tmp].next[i];            if(t==root) trie[u].fail=root;            trie[u].tmp|=trie[trie[u].fail].tmp;            q.push(u);        }    }}void work(char s[]){    int n=strlen(s+1);    for(int i=1;i<=n;i++)    {        if(s[i]=='T')        s[i]='B';        else if(s[i]=='G')        s[i]='D';    }}void find(){    for(int i=0;i<=lon;i++)    for(int p=0;p<4;p++)    {        int t=i;        while(t&&trie[t].next[p]==0)        t=trie[t].fail;        c[i][p]=trie[t].next[p];    }}int main(){    while(scanf("%d %d",&n,&m)!=EOF)    {        trieini();        char s[111];        for(int i=1;i<=n;i++)        {            scanf("%s",s+1);            scanf("%d",&a[i]);            work(s);            insert(s,i);        }        getfail();        find();        memset(dp,0,sizeof(dp));        dp[0][0][0]=1;        for(int k=0;k<m;k++)        {            int now=k%2,to=(k+1)%2;            for(int i=0;i<(1<<n);i++)            for(int j=0;j<=lon;j++)            dp[to][i][j]=0;            for(int i=0;i<(1<<n);i++)            for(int j=0;j<=lon;j++)            if(dp[now][i][j])            for(int p=0;p<4;p++)            {                int u=c[j][p];                int v=trie[u].tmp;                dp[to][i|v][u]=1;            }        }        int to=m%2;        int ans=-1;        for(int i=0;i<(1<<n);i++)        for(int j=0;j<=lon;j++)        if(dp[to][i][j])        {            int sum=0;            for(int k=1;k<=n;k++)            {                int tmp=1<<k-1;                if(tmp&i)                sum+=a[k];            }            ans=max(ans,sum);        }        if(ans>=0)        printf("%d\n",ans);        else        printf("No Rabbit after 2012!\n");    }    return 0;}