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 }