AC自动机+DP
#include <cstdio> #include <queue> #include <cstring> using namespace std; #define D(x) const int MAX_D_LEN = 25; const int MAX_LEN = 1005; const int MAX_N = 55; const int MAX_CHILD_NUM = 4; const int MAX_NODE_NUM = MAX_N * MAX_D_LEN; const int INF = 0x3f3f3f3f; char dna[MAX_LEN]; struct Trie { int next[MAX_NODE_NUM][MAX_CHILD_NUM]; int fail[MAX_NODE_NUM]; bool disease[MAX_NODE_NUM]; int node_cnt; bool vis[MAX_NODE_NUM]; //set it to false int root; int dp[MAX_LEN][MAX_NODE_NUM]; void init() { node_cnt = 0; root = newnode(); memset(vis, 0, sizeof(vis)); } int newnode() { for (int i = 0; i < MAX_CHILD_NUM; i++) next[node_cnt][i] = -1; disease[node_cnt++] = false; return node_cnt - 1; } int get_id(char a) { if (a == 'A') return 0; if (a == 'T') return 1; if (a == 'C') return 2; return 3; } void insert(char buf[]) { int now = root; for (int i = 0; buf[i]; i++) { int id = get_id(buf[i]); if (next[now][id] == -1) next[now][id] = newnode(); now = next[now][id]; } disease[now] = true; } void build() { queue<int>Q; fail[root] = root; for (int i = 0; i < MAX_CHILD_NUM; i++) if (next[root][i] == -1) next[root][i] = root; else { fail[next[root][i]] = root; Q.push(next[root][i]); } while (!Q.empty()) { int now = Q.front(); Q.pop(); for (int i = 0; i < MAX_CHILD_NUM; i++) if (next[now][i] == -1) next[now][i] = next[fail[now]][i]; else { fail[next[now][i]]=next[fail[now]][i]; if (disease[fail[next[now][i]]]) disease[next[now][i]] = true; Q.push(next[now][i]); } } } int work() { scanf("%s", dna); int len = strlen(dna); for (int i = 0; i < node_cnt; i++) { if (disease[i]) dp[len][i] = INF; else dp[len][i] = 0; } for (int i = len - 1; i >= 0; i--) { int key = get_id(dna[i]); for (int j = 0; j < node_cnt; j++) { dp[i][j] = INF; if (disease[j]) continue; for (int k = 0; k < 4; k++) { int temp = 1; if (k == key) temp = 0; int v = next[j][k]; if (disease[v]) continue; dp[i][j] = min(dp[i][j], temp + dp[i + 1][v]); D(printf("%d ", dp[i + 1][next[j][k]])); } D(printf("dp[%d][%d]=%d ", i, j, dp[i][j])); } } return dp[0][root]; } void debug() { for(int i = 0;i < node_cnt;i++) { printf("id = %3d,fail = %3d,end = %3d,chi = [",i,fail[i],disease[i]); for(int j = 0;j < MAX_CHILD_NUM;j++) printf("%2d",next[i][j]); printf("] "); } } }ac; int n; char st[MAX_D_LEN]; int main() { int case_num = 1; while (scanf("%d", &n), n) { ac.init(); for (int i = 0; i < n; i++) { scanf("%s", st); ac.insert(st); } ac.build(); int ans = ac.work(); if (ans >= INF) ans = -1; printf("Case %d: %d ", case_num++, ans); } return 0; }