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;
 11     int mask;
 12     void clear(){
 13         for(int i = 0;i < 4;i++)ch[i] = NULL;fail = NULL;
 14         mask = 0;
 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编辑  收藏  举报