Trie图(AC自动机)+DP~

View Code
1 #include <cstdio>
2 #include <cstring>
3
4 #define MIN(a,b) (a < b ? a : b)
5
6 usingnamespace std;
7
8 constint NS =4;
9 constint MAXL =32;
10 constint SIZE =1024;
11 constchar* DNA ="ACGT";
12
13 int node;
14 bool danger[SIZE];
15 int suffix[SIZE];
16 int next[SIZE][NS];
17 int queue[SIZE];
18
19 int dp[SIZE][SIZE];
20
21 char description[SIZE];
22
23 inline int getIndex(char c)
24 {
25 return strchr(DNA,c) - DNA;
26 }
27
28 int TrieInit()
29 {
30 node =0;
31 danger[0] =false;
32 suffix[0] =-1;
33 memset(next[0],-1,sizeof(next[0]));
34 return node++;
35 }
36
37 void TrieInsert(char* word,int root)
38 {
39 char* key;
40 int tmp;
41
42 key = word;
43 tmp = root;
44
45 while (*key)
46 {
47 int idx = getIndex(*key++);
48 if (next[tmp][idx] ==-1)
49 {
50 danger[node] =false;
51 suffix[node] =-1;
52 memset(next[node],-1,sizeof(next[node]));
53 next[tmp][idx] = node++;
54 }
55 tmp = next[tmp][idx];
56 }
57 danger[tmp] =true;
58 }
59
60 void getSuffix(int root)
61 {
62 int qh =-1;
63 int qe =0;
64
65 queue[0] = root;
66
67 while (qh != qe)
68 {
69 qh++;
70 int tmp = queue[qh];
71 for (int i =0;i < NS;i++)
72 if (next[tmp][i] !=-1)
73 {
74 int now = next[tmp][i];
75 int p = suffix[tmp];
76 while (p !=-1&& next[p][i] ==-1) p = suffix[p];
77 if (p ==-1) suffix[now] = root;
78 else
79 {
80 suffix[now] = next[p][i];
81 danger[now] = danger[now] || danger[next[p][i]];
82 }
83 queue[++qe] = now;
84 }
85 else
86 {
87 int p = suffix[tmp];
88 while (p !=-1&& next[p][i] ==-1) p = suffix[p];
89 if (p ==-1) next[tmp][i] = root;
90 else next[tmp][i] = next[p][i];
91 }
92 }
93 }
94
95 int main ()
96 {
97 int n;
98 char word[MAXL];
99
100 for(int cc =1;scanf("%d",&n) ==1&& n;cc++)
101 {
102 int root = TrieInit();
103 for (int i =0;i < n;i++)
104 {
105 scanf("%s",word);
106 TrieInsert(word,root);
107 }
108
109 getSuffix(root);
110
111 scanf("%s",description);
112
113 int len = strlen(description);
114
115 for (int i =0;i <= len;i++)
116 for (int j =0;j < node;j++)
117 dp[i][j] = SIZE;
118 dp[0][0] =0;
119
120 for (int i =1;i <= len;i++)
121 for (int j =0;j < node;j++)
122 if (!danger[j])
123 for (int k =0;k < NS;k++)
124 if (!danger[next[j][k]])
125 dp[i][next[j][k]] = MIN(dp[i][next[j][k]],dp[i-1][j] + (getIndex(description[i-1]) == k ?0 : 1));
126 int ans = SIZE;
127 for (int i =0;i < node;i++)
128 if (!danger[i] && ans > dp[len][i])
129 ans = dp[len][i];
130
131 printf("Case %d: %d\n",cc,ans == SIZE ?-1 : ans);
132 }
133 return0;
134 }