先将DNA片段建立AC自动机,然后在AC自动机上进行dp,dp[i][j]表示长度为i移动到j节点
修改了最少的步数。每次走到边如果和字符串不同,权值即为1;相同则为0。单词节点不能向后转移。
dp[i+1][u]=min(dp[i+1][u],dp[i][j]+c!=idx(s[i]));
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<queue>
using namespace std;
const int maxnode=55*22;
const int maxn=1010;
const int kind=4;
const int inf=0x7f7f7f7f;
struct node
{
int ch[maxnode][kind],sz;
int val[maxnode],fail[maxnode],last[maxnode];
int dp[maxn][maxnode];
void init()
{
sz=1;
memset(ch[0],0,sizeof(ch[0]));
memset(dp,inf,sizeof(dp));
}
int idx(char c)
{
if(c=='A') return 0;
if(c=='C') return 1;
if(c=='G') return 2;
if(c=='T') return 3;
}
void insert(char *s,int v)
{
int u=0,n=strlen(s);
for(int i=0;i<n;i++)
{
int id=idx(s[i]);
if(!ch[u][id])
{
memset(ch[sz],0,sizeof(ch[sz]));
val[sz]=0;
ch[u][id]=sz++;
}
u=ch[u][id];
}
val[u]=v;
}
void getFail()
{
queue<int>q;
fail[0]=0;
for(int i=0;i<kind;i++)
{
int u=ch[0][i];
if(u)
{
fail[u]=0;
q.push(u);
last[u]=0;
}
}
while(!q.empty())
{
int r=q.front();
q.pop();
for(int i=0;i<kind;i++)
{
int u=ch[r][i];
if(!u)
{
ch[r][i]=ch[fail[r]][i];
continue;
}
q.push(u);
int v=fail[r];
while(v&&!ch[v][i]) v=fail[v];
fail[u]=ch[v][i];
last[u]=val[fail[u]]?fail[u]:last[fail[u]];
}
}
}
void print(int x)
{
if(x)
{
printf("%d: %d\n",x,val[x]);
print(last[x]);
}
}
void find(char *s)
{
int j=0,n=strlen(s);
for(int i=0;i<n;i++)
{
int id=idx(s[i]);
while(j&&!ch[j][id]) j=fail[j];
j=ch[j][id];
if(val[j]) print(j);
else if(last[j]) print(last[j]);
}
}
int DP(char *s)
{
int n=strlen(s);
dp[0][0]=0;
for(int i=0;i<n;i++)
{
for(int j=0;j<sz;j++)
{
if(dp[i][j]==inf||val[j]||last[j])
continue;
for(int k=0;k<kind;k++)
{
int u=j;
while(u&&!ch[u][k]) u=fail[u];
u=ch[u][k];
int d=idx(s[i])==k?0:1;
dp[i+1][u]=min(dp[i+1][u],dp[i][j]+d);
}
}
}
int ans=inf;
for(int i=0;i<sz;i++)
{
if(val[i]||last[i])
continue;
ans=min(ans,dp[n][i]);
}
return ans==inf?-1:ans;
}
};
node ac;
char P[maxn];
int main()
{
int n,Case=0;
while(scanf("%d",&n)==1&&n!=0)
{
ac.init();
for(int i=1;i<=n;i++)
{
scanf("%s",P);
ac.insert(P,i);
}
ac.getFail();
scanf("%s",P);
int ans=ac.DP(P);
printf("Case %d: %d\n",++Case,ans);
}
return 0;
}