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 }

 

你可能感兴趣的:(AC自动机)