////HDU 2457
/////f[u]=r,r包含在u的后缀中
/////last[u]=r,r包含在u的后缀中,并且是一个单词
////每增加一个字母,状态转移一次
#include<cstdio>
#include<iostream>
#include<queue>
#include<cstring>
using namespace std;
const int inf=1<<25;
const int MN=55*22+100;
const int SZ=30;
int ch[MN][SZ];int val[MN];
int sz,tot;
void init(){tot=1;sz=4;memset(ch[0],0,sizeof(ch[0]));val[0]=0;}
int idx(char c){
if(c=='A')return 0;
else if(c=='G')return 1;
else if(c=='C')return 2;
else return 3;
}
void Ins(char *s,int v){
int u=0,n=strlen(s);
//printf("%s\n",s);
for(int i=0;i<n;i++){
int c=idx(s[i]);
if(!ch[u][c]){
memset(ch[tot],0,sizeof(ch[tot]));val[tot]=0;
ch[u][c]=tot++;
}
u=ch[u][c];
//printf("%d ",u);
}//printf("\n");
val[u]=v;
}
int f[MN],last[MN];
int getFail(){
queue<int> qq;
f[0]=0;last[0]=0;
for(int c=0;c<sz;c++){
int u=ch[0][c];
if(u){f[u]=0;last[u]=0;qq.push(u);}
}
while(!qq.empty()){
int r=qq.front();qq.pop();
for(int c=0;c<sz;c++){
int u=ch[r][c];
if(!u){
ch[r][c]=ch[f[r]][c];continue;
}
qq.push(u);
f[u]=ch[f[r]][c];
last[u]=val[f[u]]?f[u]:last[f[u]];
val[u]|=val[f[u]];
}
}
}
int dp[MN][1100],len;
char ss[30],tt[1000+100];
int dfs(int u,int x){
if(x==len)return dp[u][x]=0;
if(dp[u][x]!=-1)return dp[u][x];
int ans=inf;
for(int c=0;c<sz;c++){
int v=ch[u][c];
if(val[v])continue;
if(c==idx(tt[x+1])){
ans=min(ans,dfs(v,x+1));
}
else {
ans=min(ans,dfs(v,x+1)+1);
}
}
return dp[u][x]=ans;
}
int main(){
#ifdef DouBi
freopen("in.cpp","r",stdin);
#endif // DouBi
int n,cas=1;
while(scanf("%d",&n)!=EOF,n){
init();
for(int i=0;i<n;i++){
scanf("%s",ss);
Ins(ss,1);
}
getFail();
scanf("%s",tt+1);
len=strlen(tt+1);
memset(dp,-1,sizeof(dp));
dfs(0,0);
printf("Case %d: ",cas++);
if(dp[0][0]==inf){
printf("-1\n");
}
else printf("%d\n",dp[0][0]);
}
return 0;
}
ac自动机
最新推荐文章于 2021-08-25 21:47:52 发布