A
C
自
动
机
模
板
AC自动机模板
AC自动机模板
#include<bits/stdc++.h>
using namespace std;
function<void(void)> ____ = [](){ios_base::sync_with_stdio(false); cin.tie(0); cout.tie(0);};
const int MAXN = 2222;
const int INF = 0x3f3f3f3f;
const int AlphaSize = 4;
char s[MAXN];
int n;
int change(char c){
if(c=='A') return 0;
else if(c=='G') return 1;
else if(c=='C') return 2;
else return 3;
}
struct AC_AutoMaton{
int cnt[MAXN],last[MAXN],fail[MAXN],ch[MAXN][AlphaSize],tot;
int f[MAXN][MAXN];
queue<int> que;
void Init(){
memset(cnt,0,sizeof(cnt));
memset(ch,0,sizeof(ch));
memset(f,INF,sizeof(f));
f[0][0] = 0;
tot = 0;
}
void Insert(char *s){
int rt = 0;
for(int i = 0; s[i]!='\0'; i++){
int c = change(s[i]);
if(!ch[rt][c]) ch[rt][c] = ++tot;
rt = ch[rt][c];
}
cnt[rt]++;
}
void BuildFail(){
for(int i = 0; i < AlphaSize; i++) if(ch[0][i]){
last[ch[0][i]] = fail[ch[0][i]] = 0;
que.push(ch[0][i]);
}
while(!que.empty()){
int u = que.front();
que.pop();
for(int i = 0; i < AlphaSize; i++){
int v = ch[u][i];
if(!v){
ch[u][i] = ch[fail[u]][i];
continue;
}
int to = fail[u];
while(to&&!ch[to][i]) to = fail[to];
fail[v] = ch[to][i];
if(cnt[fail[v]]) last[v] = fail[v];
else last[v] = last[fail[v]];
que.push(v);
}
}
}
bool check(int rt){
if(!rt) return false;
return (cnt[rt]!=0) || check(last[rt]);
}
int Match(char *s, int len){
for(int i = 1; i <= len; i++){
int c = change(s[i]);
for(int cur = 0; cur < AlphaSize; cur++){
for(int pre = 0; pre <= tot; pre++){
if(f[i-1][pre]==INF) continue;
if(check(ch[pre][cur])) continue;
else f[i][ch[pre][cur]] = min(f[i][ch[pre][cur]],f[i-1][pre]+(cur!=c));
}
}
}
int res = INF;
for(int i = 0; i <= tot; i++) res = min(res,f[len][i]);
return res==INF?-1:res;
}
}Aho;
int main(){
int kase = 0;
while(scanf("%d",&n)!=EOF && n){
Aho.Init();
for(int i = 1; i <= n; i++){
scanf("%s",s);
Aho.Insert(s);
}
Aho.BuildFail();
scanf("%s",s+1);
int len = strlen(s+1);
printf("Case %d: %d\n",++kase,Aho.Match(s,len));
}
return 0;
}