poj 3691 DNA repair AC自动机+DP

  1 /*
2 * POJ - 3691 DNA repair
3 * 第一道AC自动机 + DP
4 *
5 * 题意:
6 * 给n(n<=50)个模板串(长度<=20)和一个主串(长度<=1000),
7 * 求最少修改几次主串能让模板串都不在主串中出现,
8 * 无法满足要求的话输出-1.
9 *
10 * 思路:
11 * 建一个Trie图,相当于DFA(有限状态自动机),在图上DP,
12 * dp[i][j]:在长为i的主串中匹配到Trie图上的j节点时,
13 * 最少需要修改几处满足要求。
14 *
15 * 错误地方:
16 * 1. 建AC自动机的时候fail初始化为0了(事后发现好像没多大关系)
17 * 2. 建Trie图的时候,继承tag的时候写错了,写成继承fail的tag了,
18 * 应该继承的是fail的child[i]的tag,本来就应该如此
19 * 3. DP方程是抄的网上的,改了n遍,以为是DP方程错了,
20 * 结果是继承tag的时候错了.
21 *
22 * ——DP,内伤啊。。
23 * ——2011-11-09/23:56:38 离福州regional还有10天,加油AC!
24 */
25
26 #include <stdio.h>
27 #include <iostream>
28 #include <math.h>
29 #include <string.h>
30 using namespace std;
31
32 #define kind 4
33 #define begin 0
34 #define cls(a, b) memset(a, b, sizeof(a))
35 #define N 1005
36 #define inf 0x3f3f3f3f
37
38 int root, tot;
39 int que[N], head, tail;
40 int map[128];
41
42 struct node{
43 int ch[kind], tag, fail;
44 void init(){ cls(ch, 0); tag=0; fail=-1; }
45 }T[N];
46
47 void init_root()
48 {
49 root = tot = 0;
50 T[root].init();
51 }
52
53 void insert(char *s)
54 {
55 int p = root, idx;
56 while(*s)
57 {
58 idx = map[*(s++)];
59 if(!T[p].ch[idx])
60 {
61 T[++tot].init();
62 T[p].ch[idx] = tot;
63 }
64 p = T[p].ch[idx];
65 }
66 T[p].tag = 1;
67 }
68
69 void build_AC()
70 {
71 head = tail = 0;
72 que[tail++] = root;
73 while(head < tail)
74 {
75 int u = que[head++];
76 for(int i=0; i<kind; i++)
77 {
78 if(T[u].ch[i])
79 {
80 int son = T[u].ch[i];
81 int p = T[u].fail;
82 if(u == root) T[son].fail = root;
83 else{
84 T[son].fail = T[p].ch[i];
85 if(T[T[p].ch[i]].tag) T[son].tag = T[T
86
87 [p].ch[i]].tag; //传递"串尾"信息
88 }
89 que[tail++] = son;
90 }else{
91 if(u == root) T[u].ch[i] = root;
92 else T[u].ch[i] = T[T[u].fail].ch[i];
93 }
94 }
95 }
96 }
97
98 int f[N][N];
99 void solve()
100 {
101 int n, i, j, k,tmp, d=1;
102 char str[1005];
103 map['A'] = 0; map['T'] = 1;
104 map['C'] = 2; map['G'] = 3;
105 while(~scanf("%d", &n) && n)
106 {
107 init_root();
108 for(i=1; i<=n; i++)
109 {
110 scanf("%s", str);
111 insert(str);
112 }
113 build_AC();
114 scanf("%s", str);
115 n = strlen(str);
116 cls(f, 0x3f);
117 f[0][0] = 0;
118 for(i=0; i<n; i++)
119 for(j=0; j<=tot; j++) //之前这里少个等号,没想到也AC了
120 if(f[i][j]<inf)
121 for(k=0; k<kind; k++)
122 if(!T[j].tag && !T[T[j].ch[k]].tag)
123 {
124 tmp = f[i][j] + (k != map[str
125
126 [i]]);
127 if(tmp < f[i+1][T[j].ch[k]])
128 f[i+1][T[j].ch[k]] = tmp;
129 }
130 int ans = inf;
131 for(i=0; i<=tot; i++)
132 if(f[n][i] < ans) ans = f[n][i];
133 printf("Case %d: %d\n", d++, ans==inf?-1:ans);
134 }
135 }
136
137 int main(){
138 #ifdef Nstd
139 freopen("E:\\workspace\\in.txt", "r+", stdin);
140 #endif
141 solve();
142 return 0;
143 }



原文地址:https://www.cnblogs.com/Nstd/p/2243765.html