POJ 3691 DNA repair(AC自动机+DP)

题目链接

能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\n");
124         else
125         printf("%d\n",ans);
126     }
127     return 0;
128 }

 

posted @ 2013-07-28 14:01  Naix_x  阅读(208)  评论(0编辑  收藏  举报