hdu 4057

来源:互联网 发布:Windows 10 微信 编辑:程序博客网 时间:2024/06/07 10:36

http://acm.hdu.edu.cn/showproblem.php?pid=4057


我不喜欢把它叫做ac自动机+dp ,个人觉得叫做ac自动机上的dp更好,原因就在于我们用ac自动机的一个个节点的状态来构建状态和状态之间的转移,至于非要为什么用ac自动机来构建状态,个人认为它包含了题目给出的说有字串的转移之间的信息(保证正确),而且状态数很少(保证了时间复查度小)

dp[node ][ state ] 表示当前长度到达 node节点,包含state字串(用二进制状态压缩),因为题目说了每个字串只能计算一次,否则的话 直接dp【node】 每次取最大值就可以了

#include <cstdlib>#include <iostream>#include <algorithm> using namespace std;const int maxn=1010;int chd[maxn][4],fail[maxn],word[maxn],sz,sw[128];bool dp1[1010][1050],dp2[1010][1050];int n,len;char s[110];int val[20];void Ins(char *a,int val){     int p=0;    for(;*a;a++)         {        int id=sw[*a];                         if(!chd[p][id])        {             memset(chd[sz],0,sizeof(chd[sz]));                            word[sz]=0;             chd[p][id]=sz++;        }        p=chd[p][id];    }    word[p]|=(1<<val);}int Que[maxn];void ac(){    int *s=Que,*e=Que;     for(int i=0;i<4;i++)           if(chd[0][i])      {          *e++=chd[0][i];          fail[chd[0][i]]=0;      }    while(s!=e)      {         int p=*s++;         for(int i=0;i<4;i++)                        if(chd[p][i])           {                *e++=chd[p][i];                fail[chd[p][i]]=chd[fail[p]][i];                word[chd[p][i]]|=word[fail[chd[p][i]]];           }           else             chd[p][i]=chd[fail[p]][i];    }} void solve(){    memset(dp1,0,sizeof(dp1));      memset(dp2,0,sizeof(dp2));      dp1[0][0]=1;    int Max=(1<<n);    for(int k=0;k<len;k++)    {         for(int i=0;i<sz;i++)                 for(int j=0;j<Max;j++)          if(dp1[i][j])          {               for(int r=0;r<4;r++)                             dp2[chd[i][r]][j|word[chd[i][r]]]=1;          }        memcpy(dp1,dp2,sizeof(dp2));          memset(dp2,0,sizeof(dp2));      }    long long ans=-1;    for(int i=0;i<sz;i++)            for(int j=0;j<Max;j++)      if(dp1[i][j])       {           long long tmp=0;                    for(int r=0;r<n;r++)                          if(j&(1<<r)) tmp+=(long long)val[r];           if(ans<tmp) ans=tmp;       }     if(ans>=0) cout<<ans<<endl;      else cout<<"No Rabbit after 2012!"<<endl;}int main(int argc, char *argv[]){    sw['A']=0;    sw['T']=1;    sw['C']=2;    sw['G']=3;    while(cin>>n>>len)    {          sz=1;          memset(chd[0],0,sizeof(chd[0]));          for(int i=0;i<n;i++)            {             cin>>s>>val[i];             Ins(s,i);          }         ac();         solve();      }   // system("PAUSE");    return EXIT_SUCCESS;}