hdu3341Lost's revenge(ac自动机+dp)

链接

类似的dp省赛时就做过了,不过这题卡内存,需要把当前状态hash一下,可以按进制来算出当前的状态,因为所有的状态数是不会超过10*10*10*10的,所以完全可以把这些存下来。

刚开始把trie的的遍历节点写在外层循环了,一直WA,后来想了一下,状态是只会向前走的,但是节点不一样,如果由 当前节点的状态-》下一节点的状态,下一节点有可能是在当前节点之前的,这样是不对的,所以需要由当前状态的节点 -》下一状态的节点 。

  1 #include <iostream>
  2 #include<cstdio>
  3 #include<cstring>
  4 #include<algorithm>
  5 #include<stdlib.h>
  6 #include<vector>
  7 #include<cmath>
  8 #include<queue>
  9 #include<set>
 10 using namespace std;
 11 #define N 510
 12 #define LL long long
 13 #define INF -1
 14 const double eps = 1e-8;
 15 const double pi = acos(-1.0);
 16 const double inf = ~0u>>2;
 17 const int child_num = 4;
 18 char vir[22],s[105];
 19 int mp[3200010];
 20 class AC
 21 {
 22     private:
 23     int ch[N][child_num];
 24     int Q[N];
 25     int fail[N];
 26     int val[N];
 27     int id[127];
 28     int sz;
 29     int dp[N][20000];
 30     public:
 31     void init()
 32     {
 33         fail[0] = 0;
 34         id['A'] = 0,id['G'] = 1,id['T'] = 2,id['C'] = 3;
 35     }
 36     void reset()
 37     {
 38         memset(ch[0],0,sizeof(ch[0]));
 39         memset(val,0,sizeof(val));
 40         sz = 1;
 41     }
 42     void insert(char *a,int key)
 43     {
 44         int p =0 ;
 45         for( ; *a ; a++)
 46         {
 47             int d = id[*a];
 48             if(ch[p][d]==0)
 49             {
 50                 memset(ch[sz],0,sizeof(ch[sz]));
 51                 ch[p][d] = sz++;
 52             }
 53             p = ch[p][d];
 54         }
 55         val[p] += key;
 56     }
 57     void construct()
 58     {
 59         int i,head=0,tail = 0;
 60         for(i = 0;i < child_num ; i++)
 61         {
 62             if(ch[0][i])
 63             {
 64                 fail[ch[0][i]] = 0;
 65                 Q[tail++] = ch[0][i];
 66             }
 67         }
 68         while(head!=tail)
 69         {
 70             int u = Q[head++];
 71             val[u]+=val[fail[u]];
 72             for(i =0 ; i < child_num ; i++)
 73             {
 74                 if(ch[u][i])
 75                 {
 76                     fail[ch[u][i]] = ch[fail[u]][i];
 77                     Q[tail++] = ch[u][i];
 78                 }
 79                 else ch[u][i] = ch[fail[u]][i];
 80             }
 81         }
 82     }
 83     void work(char *s,int kk)
 84     {
 85         int k = strlen(s);
 86         int num[5]= {0},pp[5];
 87         memset(num,0,sizeof(num));
 88         int o = 0 ,i,j,g,e,z,y;
 89         for(i = 0 ; i < k ;i++)
 90         {
 91             num[id[s[i]]]++;
 92         }
 93         pp[0] = 1;
 94         for(i = 1; i <= 4 ; i++)
 95         pp[i] = pp[i-1]*42;
 96         memset(mp,-1,sizeof(mp));
 97         for(i = 0 ; i <= num[0] ; i++)
 98             for(j = 0;j <= num[1] ; j++)
 99                 for(g =0 ; g <= num[2] ; g++)
100                     for(e = 0 ; e <= num[3] ;e++)
101                     {
102                         int sum = e*pp[3]+g*pp[2]+j*42+i;
103                         o++;
104                         mp[sum] = o;
105                     }
106         memset(dp,-1,sizeof(dp));
107         dp[0][1] = 0;
108         for(i = 0 ; i <= num[0] ; i++)
109             for(j = 0;j <= num[1] ; j++)
110                 for(g = 0 ; g <= num[2] ; g++)
111                     for(e = 0 ; e <= num[3] ;e++)
112                     {
113                         for(z = 0  ;z < sz ; z++)
114                         {
115                             int sum = e*pp[3]+g*pp[2]+j*42+i;
116                             if(dp[z][mp[sum]]==-1) continue;
117                             for(y = 0; y < child_num ; y++)
118                             {
119                                 int yy = ch[z][y];
120                                 int ss = pp[y]+sum;
121                                 if(mp[ss]==-1) continue;
122                                 dp[yy][mp[ss]] = max(dp[yy][mp[ss]],dp[z][mp[sum]]+val[yy]);
123                             }
124                         }
125                     }
126         int ans = 0;
127         for(i = 0;i < sz ; i++)
128         {
129             ans=max(dp[i][o],ans);
130         }
131         printf("Case %d: ",kk);
132         printf("%d\n",ans);
133     }
134 }ac;
135 int main()
136 {
137     int n,kk=0;
138     ac.init();
139     while(scanf("%d",&n)&&n)
140     {
141         ac.reset();
142         kk++;
143         while(n--)
144         {
145             scanf("%s",vir);
146             ac.insert(vir,1);
147         }
148         ac.construct();
149         scanf("%s",s);
150         ac.work(s,kk);
151     }
152     return 0;
153 }
View Code

 

posted @ 2014-05-25 10:04  _雨  阅读(245)  评论(0编辑  收藏  举报