HDOJ 4057 - Rescue the Rabbit 简单的AC自动机+状态压缩DP

来源:互联网 发布:java 网络通信框架 编辑:程序博客网 时间:2024/04/29 12:38

                 题意:

                         众所周知..DNA序列由"A","G","T","C"组成....

                         现在N个DNA序列(每个长度没说..假设都小于1000吧...1<=N<=10)...并且告诉每个DNA序列能得到的分数Wi,(|Wi|<=100)...

                         若一个DNA串包含其中的某些串..那么得分就是包括的串分数之和(一个串不管出现了多少次..只算一次)..

                         问..若构造长度为M(1<=M<=100)的DNA序列...能得到的最大分数为多少...

                 题解:

                          裸AC自动机...然后10个DNA子串...状态压缩DP...复杂度有些高 100*1000*1024*4...好久没写AC自动机了..差点写跪....再一个写程序的时候memset最好直接用for循环去代替吧..常数比较大....


Program:

#include<iostream>#include<stdio.h>#include<cmath>#include<queue>#include<algorithm>#include<string.h>#define MAXN 10002using namespace std;struct node{      int son[4],fail,w;}P[MAXN];char s[1005];bool dp[2][1015][1<<10];int val[1<<10],turn[30],num;void initial(int h){      int x;      for (x=0;x<4;x++) P[h].son[x]=0;      P[h].fail=P[h].w=0;}void Built_Trie(int n){      int h,k,t,x,i,y,len;      initial(0),num=0;      for (t=0;t<n;t++)      {              scanf("%s%d",s+1,&val[t]),len=strlen(s+1);              if (len>100) { val[t]=0; continue; }              h=0;              for (i=1;i<=len;i++)              {                      x=turn[s[i]-'A'];                      if (!P[h].son[x]) P[h].son[x]=++num,initial(num);                      h=P[h].son[x];              }              P[h].w|=1<<t;      }}void Built_AC(){      int h,k,x;      queue<int> Q;      while (Q.size()) Q.pop();      for (x=0;x<4;x++)         if (P[0].son[x])           Q.push(P[0].son[x]);      while (Q.size())      {             h=Q.front(),Q.pop();             for (x=0;x<4;x++)             {                     k=P[h].fail;                     while (k && !P[k].son[x]) k=P[k].fail;                     P[P[h].son[x]].fail=P[k].son[x];                     if (!P[h].son[x])                          P[h].son[x]=P[k].son[x];                     else                     {                          Q.push(P[h].son[x]);                          k=P[h].fail;                          while (1)                          {                                 P[P[h].son[x]].w|=P[P[k].son[x]].w,k=P[k].fail;                                if (!k) break;                          }                     }             }      }}int AC_DP(int n,int L){      int l,w,h,x,h1,w1,temp,ans=-1,g=0;      memset(dp,false,sizeof(dp));      dp[g][0][0]=true;      for (l=1;l<=L;l++)      {              g=1-g;              for (h=0;h<=num;h++)                 for (w=0;w<(1<<n);w++)                    dp[g][h][w]=false;              for (h=0;h<=num;h++)                 for (w=0;w<(1<<n);w++)                    if (dp[1-g][h][w])                       for (x=0;x<4;x++)                       {                              h1=P[h].son[x];                              w1=w|P[h1].w;                              dp[g][h1][w1]=true;                       }      }      for (h=0;h<=num;h++)        for (w=0;w<(1<<n);w++)          if (dp[g][h][w])              dp[g][0][w]=true;      for (w=0;w<(1<<n);w++)          if (dp[g][0][w])          {                  temp=0;                  for (x=0;x<n;x++)                     if (w & 1<<x)                        temp+=val[x];                   ans=max(ans,temp);          }      return ans;}int main(){      int n,l,ans;       turn['A'-'A']=0,turn['G'-'A']=1,      turn['T'-'A']=2,turn['C'-'A']=3;      while (~scanf("%d%d",&n,&l))      {               Built_Trie(n);               Built_AC();               ans=AC_DP(n,l);               if (ans<0) puts("No Rabbit after 2012!");                     else printf("%d\n",ans);      }      return 0;}