先用AC自动机构建一个不含有任何病毒串的 DFA , dp[i][j] 表示到目标串的第 i 个字符,DFA 状态为 j 时的最小修改数量。则 dp[i][ son[j] ]= min{ dp[i][ son[j] ], dp[i-1][j]+ (tran[j][ son[j] ]!= str[i] ) } tran[j][ son[j] ]表示从 j 到 son[j] 经过的字母边。
代码:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define min(a,b) ((a)<(b)?(a):(b))
#define inf 0x7fffffff
int const N= 2000;
struct Node{
int next[4];
int fail, flag;
void init(){
for( int i= 0; i< 4; ++i ) next[i]= 0;
fail= -1; flag= 0;
}
}tb[N];
char str[N];
int dp[N][N], n, cnt;
int inline toInt( char ch ){
if( ch== 'A' ) return 0;
if( ch== 'T' ) return 1;
if( ch== 'G' ) return 2;
if( ch== 'C' ) return 3;
}
void insert( char*s ){
int rt= 0;
while( *s ){
int t= toInt( *s );
if( tb[rt].next[t]== 0 ){
tb[++cnt].init();
tb[rt].next[t]= cnt;
}
rt= tb[rt].next[t]; s++;
}
tb[rt].flag= 1;
}
int que[N], head, tail;
void bfs(){
int p, q, now;
head= 0, tail= 0, que[0]= 0;
while( head<= tail ){
now= que[head++];
for( int t= 0; t< 4; ++t )
if( tb[now].next[t] ){
p= tb[now].next[t]; q= tb[now].fail;
while( q!= -1 && !tb[q].next[t] ) q= tb[q].fail;
if( q== -1 ) tb[p].fail= 0;
else{
tb[p].fail= tb[q].next[t];
tb[p].flag|= tb[ tb[p].fail ].flag;
}
que[++tail]= p;
}
else{
q= tb[now].fail;
while( q!= -1 && !tb[q].next[t] ) q= tb[q].fail;
if( q== -1 ) tb[now].next[t]= 0;
else tb[now].next[t]= tb[q].next[t];
}
}
}
int main(){
int test= 1;
while( scanf("%d",&n)!= EOF ){
if( n== 0 ) return 0;
cnt= 0; tb[0].init();
for( int i= 0; i< n; ++i ){
scanf("%s", str );
insert( str );
}
bfs();
scanf("%s",str);
int len= strlen(str);
for( int i= 0; i<= len; ++i )
for( int j= 0; j<= cnt; ++j ) dp[i][j]= inf;
dp[0][0]= 0;
for( int i= 1; i<= len; ++i ){
for( int j= 0; j<= cnt; ++j )
if( dp[i-1][j]!= inf && !tb[j].flag ){
for( int t= 0; t< 4; ++t )
if( !tb[ tb[j].next[t] ].flag ){
int k= tb[j].next[t];
dp[i][k]= min( dp[i][k], dp[i-1][j]+ ( t!= toInt( str[i-1] ) ) );
}
}
}
int ans= inf;
for( int i= 0; i<= cnt; ++i ) ans= min( ans, dp[len][i] );
printf("Case %d: ", test++ );
if( ans== inf ) printf("-1\n");
else printf("%d\n", ans );
}
return 0;
}