# hdu 4057 Rescue the Rabbit

给出n(n<=10)个串，每个串有个权值，然后让你构造一个长度为l(l<=100)的串，如果他包含给出的串就得到相应的权值，求可能得到的最大权值

AC自动机+DP，很显然要建立自动机，然后在上面跑，如果不要求每个串的权值只能获取一次，那么直接跑来跑去的就行，但是因为只能取一次，串很少，可以状态压缩DP,dp[i][j][k]记录前i个字符走到j状态并且已经获得的串状态为k时的最优解。需要滚动数组优化空间--

  1 #include<cstdio>
2 #include<cstring>
3 #include<queue>
4 #include<algorithm>
5 using namespace std;
6 const int N = 1010;
7 const int inf = ~0u>>2;
8 int hash[129];
9 struct node{
10     node *ch[4],*fail;
12     void clear(){
13         for(int i = 0;i < 4;i++)ch[i] = NULL;fail = NULL;
15     }
16 };
17 node stk[N*10];
18 bool dp[2][N][1024];
19 int score[1024];
20 struct Trie{
21     node *root;int top;
22     node* newnode(){
23         node *p = &stk[top++];
24         p -> clear();
25         return p;
26     }
27     void init(){
28         top = 0;
29         root = newnode();
30     }
31     void insert(char *s,int number){
32         node *p = root;int len = strlen(s);
33         for(int i = 0;i < len;i++){
34             int id = hash[s[i]];
35             if(p -> ch[id] == NULL)
36                 p -> ch[id] = newnode();
37             p = p -> ch[id];
38         }
39         p -> mask |= 1<<number;
40     }
41     void build(){
42         queue<node*> Q;
43         root -> fail = root;
44         for(int i = 0;i < 4;i++)
45             if(root -> ch[i] == NULL)
46                 root -> ch[i] = root;
47             else{
48                 Q.push(root -> ch[i]);
49                 root -> ch[i] -> fail = root;
50             }
51         while(!Q.empty()){
52             node *p = Q.front();Q.pop();
53             for(int i = 0;i < 4;i++)
54                 if(p -> ch[i] == NULL)
55                     p -> ch[i] = p -> fail -> ch[i];
56                 else{
57                     Q.push(p -> ch[i]);
58                     p -> ch[i] -> fail = p -> fail -> ch[i];
59                     p -> ch[i] -> mask |= p -> ch[i] -> fail -> mask;
60                 }
61         }
62     }
63     int solve(int len,int number){
64         memset(dp,0,sizeof(dp));
65         dp[0][0][0] = true;
66         for(int i = 1;i <= len;i++){
67             memset(dp[i&1],0,sizeof(dp[i&1]));
68             for(int j = 0;j < top;j++){
69                 node *cur = &stk[j];
70                 for(int st = 0;st < 1<<number;st++){
71                     if(dp[(i+1)&1][j][st]){
72                         for(int k = 0;k < 4;k++){
73                             node *next = cur -> ch[k];
74                             dp[i&1][next - stk][st | next -> mask] = 1;
75                         }
76                     }
77                 }
78             }
79         }
80         int ans = -inf;
81         for(int i = 0;i < top;i++)
82             for(int j = 0;j < 1<<number;j++)
83                 if(dp[len&1][i][j]){
84                     ans = max(ans,score[j]);
85                 }
86         return ans;
87     }
88 };
89 Trie AC;
90 char s[N];
91 int w[11];
92 int main(){
93     hash['A'] = 0;hash['C'] = 1;hash['G'] = 2;hash['T'] = 3;
94     int n,l;
95     int cas = 1;
96     while(~scanf("%d%d",&n,&l)){
97         AC.init();
98         for(int i = 0;i < n;i++){
99             scanf("%s%d",s,&w[i]);
100             AC.insert(s,i);
101         }
102         for(int i = 0;i < 1<<n ;i++){
103             score[i] = 0;
104             for(int j = 0;j < n;j++)
105                 if(i&(1<<j))score[i] += w[j];
106         }
107         AC.build();
108         int ans = AC.solve(l,n);
109         //printf("Case %d\n",cas++);
110         if(ans < 0)puts("No Rabbit after 2012!");
111         else printf("%d\n",ans);
112     }
113     return 0;
114 }

posted @ 2013-08-12 22:20  silver__bullet  阅读(330)  评论(0编辑  收藏  举报