能AC还是很开心的...此题没有POJ2778那么难,那个题还需要矩阵乘法,两个题有点相似的。
做题之前,把2778代码重新看了一下,回忆一下当时做题的思路,回忆AC自动机是干嘛的...
状态表示dp[i][j]长度为i的以j串为结束的最小改变数目。AC自动机预处理一下,然后DP。
卡内存+不知道状态数,MLE+RE+WA了多次。
1 #include <iostream> 2 #include <cstring> 3 #include <cstdio> 4 #include <queue> 5 #include <algorithm> 6 #include <cstdlib> 7 using namespace std; 8 #define N 2222222 9 #define INF 10000000 10 int trie[N][4]; 11 int o[N]; 12 int que[N]; 13 int fail[N]; 14 int dp[1001][1001]; 15 int t; 16 void CL() 17 { 18 memset(trie,-1,sizeof(trie)); 19 memset(o,0,sizeof(o)); 20 t = 1; 21 } 22 int judge(char s) 23 { 24 switch(s) 25 { 26 case'A':return 0; 27 case'C':return 1; 28 case'G':return 2; 29 case'T':return 3; 30 } 31 return 0; 32 } 33 void insert(char *str) 34 { 35 int i,len,root; 36 root = 0; 37 len = strlen(str); 38 for(i = 0;i < len;i ++) 39 { 40 if(trie[root][judge(str[i])] == -1) 41 trie[root][judge(str[i])] = t ++; 42 root = trie[root][judge(str[i])]; 43 } 44 o[root] = 1; 45 } 46 void build_ac() 47 { 48 int head,tail,front,i; 49 head = tail = 0; 50 for(i = 0;i < 4;i ++) 51 { 52 if(trie[0][i] != -1) 53 { 54 fail[trie[0][i]] = 0; 55 que[tail++] = trie[0][i]; 56 } 57 else 58 { 59 trie[0][i] = 0; 60 } 61 } 62 while(head != tail) 63 { 64 front = que[head++]; 65 if(o[fail[front]]) 66 o[front] = 1; 67 for(i = 0;i < 4;i ++) 68 { 69 if(trie[front][i] != -1) 70 { 71 que[tail++] = trie[front][i]; 72 fail[trie[front][i]] = trie[fail[front]][i]; 73 } 74 else 75 { 76 trie[front][i] = trie[fail[front]][i]; 77 } 78 } 79 } 80 } 81 int main() 82 { 83 int n,i,j,k,len,flag,cas = 1; 84 char str[2001]; 85 while(scanf("%d",&n)!=EOF) 86 { 87 if(n == 0) break; 88 CL(); 89 for(i = 1;i <= n;i ++) 90 { 91 scanf("%s",str); 92 insert(str); 93 } 94 build_ac(); 95 scanf("%s",str); 96 len = strlen(str); 97 for(i = 0;i <= len;i ++) 98 { 99 for(j = 0;j <= t;j ++) 100 dp[i][j] = INF; 101 } 102 dp[0][0] = 0; 103 for(i = 0;i < len;i ++) 104 { 105 for(j = 0;j < t;j ++) 106 { 107 if(o[j]) continue; 108 for(k = 0;k < 4;k ++) 109 { 110 if(o[trie[j][k]]) continue; 111 flag = !(k == judge(str[i])); 112 dp[i+1][trie[j][k]] = min(dp[i+1][trie[j][k]],dp[i][j] + flag); 113 } 114 } 115 } 116 int ans = INF; 117 for(i = 0;i < t;i ++) 118 { 119 ans = min(ans,dp[len][i]); 120 } 121 printf("Case %d: ",cas ++); 122 if(ans == INF) 123 printf("-1 "); 124 else 125 printf("%d ",ans); 126 } 127 return 0; 128 }