#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cmath>
#include <cstring>
#include <string.h>
#include <queue>
#include <vector>
#define inf 1<<30
using namespace std; //hdu 2457 ac自动机dp
int n, k, T, dp[1010][1010]; //dp数组第一维表示长度,第二维表示到什么节点,dp[i][j]表示长度为i,当前为节点j的时候,需要修改的最少字符数。
struct node
{
int isword;
int fail;
int next[4];
void init()
{
for(int t=0; t<4; ++t)
next[t]=0;
isword=0;
fail=-1;
}
}a[1010];
int f(char c)
{
if(c=='A')return 0;
if(c=='G')return 1;
if(c=='C')return 2;
if(c=='T')return 3;
}
void insert(char *p)
{
int t, h, g=0, j=strlen(p);
for(t=0; t<j; ++t)
{
h=f(p[t]);
if(!a[g].next[h])
{
a[k].init();
a[g].next[h]=k++;
}
g=a[g].next[h];
}
a[g].isword=1;
return ;
}
void acAutomation() //优化过的,可以当模板
{
int t, temp;
queue<int> q;
q.push(0);
while(!q.empty())
{
int s=q.front();
q.pop();
for(t=0; t<4; ++t)
{
if(a[s].next[t]==0)
{
if(s==0)a[s].next[t]=0;
else a[s].next[t]=a[a[s].fail].next[t]; //注意这里
}
else
{
temp=a[s].fail;
if(s==0)
{
a[a[s].next[t]].fail=0;
}
else
{
while(temp!=-1)
{
if(a[temp].next[t])
{
a[a[s].next[t]].fail=a[temp].next[t];
break;
}
temp=a[temp].fail;
}
if(temp==-1)
a[a[s].next[t]].fail=0;
}
a[a[s].next[t]].isword|=a[a[a[s].next[t]].fail].isword;
q.push(a[s].next[t]);
}
}
}
}
void solve(char *p)
{
int t, j, i, h, g=strlen(p);
for(i=0; i<=g; ++i) //初始化
{
for(t=0; t<k; ++t)
dp[i][t]=inf;
}
dp[0][0]=0;
for(i=0; i<g; ++i)
{
for(j=0; j<k; ++j)
{
if(a[j].isword)continue;
for(t=0; t<4; ++t)
{
h=a[j].next[t];
if(a[h].isword)continue;
dp[i+1][h]=min(dp[i+1][h], dp[i][j]+(f(p[i])!=t)); //状态转移,只要是字符串的字符在字典树上则加0,不在则加1
}
}
}
int ans=inf;
for(t=0; t<k; ++t)
ans=min(ans, dp[g][t]); //长度为g的最小值
printf("Case %d: ", ++T);
if(ans==inf) //不能改变
{
printf("-1\n");
}
else printf("%d\n", ans);
return ;
}
int main()
{
int t;
char p[30], q[1010];
while(scanf("%d", &n)&&n)
{
a[0].init();
k=1;
for(t=0; t<n; ++t)
{
scanf("%s", p);
insert(p);
}
scanf("%s", q);
acAutomation();
solve(q);
}
return 0;
}
hdu 2457 ac自动机dp
最新推荐文章于 2022-06-19 17:48:58 发布