一、题目
二、思路和代码
1.思路
经典的AC自动机+dp (x2)
dp[i][j]表示考虑前i个字符, 且后缀模式为状态 [root, j] 的最少处理次数
2.读入数据
代码如下:
#include <cstring>
#include <iostream>
#include <queue>
using namespace std;
const int maxn = 2000;
const int inf = 0x3f3f3f3f;
struct node {
int next[4];
int cnt, end;
void init() {
memset(next, 0, sizeof(next));
cnt = 0;
end = 0;
}
} trie[maxn];
int cnt, fail[maxn];
int ans;
char str[maxn];
int dp[maxn][maxn];
int n;
void init() {
cnt = 0, ans = inf;
memset(fail, 0, sizeof(fail));
memset(dp, 0x3f, sizeof(dp));
dp[0][0] = 0;
trie[0].init();
}
void insert(char *s) {
int len = strlen(s);
int u = 0;
for (int i = 0; i < len; i++) {
int c;
if (s[i] == 'A') c = 0;
if (s[i] == 'C') c = 1;
if (s[i] == 'G') c = 2;
if (s[i] == 'T') c = 3;
if (!trie[u].next[c]) {
trie[u].next[c] = ++cnt;
trie[cnt].init();
}
u = trie[u].next[c];
}
trie[u].end = 1;
trie[u].cnt++;
}
void getFail() {
queue<int> q;
fail[0] = 0;
for (int i = 0; i < 4; i++) {
if (trie[0].next[i]) {
fail[trie[0].next[i]] = 0;
q.push(trie[0].next[i]);
}
}
while (!q.empty()) {
int u = q.front();
q.pop();
for (int i = 0; i < 4; i++) {
int v = trie[u].next[i];
if (!v) {
trie[u].next[i] = trie[fail[u]].next[i];
} else {
fail[v] = trie[fail[u]].next[i];
q.push(v);
}
}
trie[u].cnt += trie[fail[u]].cnt;
trie[u].end |= trie[fail[u]].end;
}
}
int main() {
// freopen("in.txt", "r", stdin);
// freopen("out.txt", "w", stdout);
int cas = 0;
while (scanf("%d", &n) && n) {
init();
for (int i = 0; i < n; i++) {
scanf("%s", str);
insert(str);
}
getFail();
scanf("%s", str);
int len = strlen(str);
for (int i = 0; i < len; i++) {
for (int j = 0; j <= cnt; j++) {
for (int k = 0; k < 4; k++) {
int v = trie[j].next[k];
if (trie[v].end) continue;
int c;
if (str[i] == 'A') c = 0;
if (str[i] == 'C') c = 1;
if (str[i] == 'G') c = 2;
if (str[i] == 'T') c = 3;
if (c == k) { // str[i]==trie[j].next[k]
dp[i + 1][v] = min(dp[i + 1][v], dp[i][j]);
} else {
dp[i + 1][v] = min(dp[i + 1][v], dp[i][j] + 1);
}
}
}
}
for (int i = 0; i <= cnt; i++) {
ans = min(ans, dp[len][i]);
}
ans = ans == inf ? -1 : ans;
printf("Case %d: %d\n", ++cas, ans);
}
return 0;
}