#include <iostream>
#include <cstring>
#include <cstdio>
#include <queue>
using namespace std;
const int N=1005;
const int INF=0x3ffffff;
int tot=0,dp[N][N];
struct node{
int son[4],fail;
bool dan;
}trie[N];
void init(){
for(int i=0;i<=tot;i++){
trie[i].fail=trie[i].dan=0;
for(int j=0;j<4;j++)
trie[i].son[j]=0;
}
tot=0;
}
int get(char c){
switch(c){
case 'A': return 0;
case 'T': return 1;
case 'C': return 2;
default: return 3;
}
}
void Insert(char *s){
int p = 0;
for(int i=0,len=strlen(s);i<len;i++){
int t=get(s[i]);
if(!trie[p].son[t]){
trie[p].son[t]=++tot;
}
p=trie[p].son[t];
}
trie[p].dan=true;
}
void build_ac(){
queue<int> Q;
for(int i=0;i<4;i++)
if(trie[0].son[i])
Q.push(trie[0].son[i]);
while(!Q.empty()){
int u=Q.front();Q.pop();
for(int i=0;i<4;i++){
int t=trie[u].son[i];
int f=trie[u].fail;
if(t){
trie[t].fail=trie[f].son[i];
if(trie[trie[f].son[i]].dan){
trie[t].dan=true;
}
Q.push(trie[u].son[i]);
}else trie[u].son[i]=trie[f].son[i];
}
}
}
//dp[i][j],表示到达查找串第i个字符时,对应于AC自动机的j节点所需要的最小改变数。\
状态转移为dp[i][j] = min( dp[i][j], dp[i-1][j]+get(s[i-1])!=k))
int Query(char *s){
for(int i=0,len=strlen(s);i <= len;i++)
for(int j=0;j <= tot;j++)
dp[i][j]=INF;
dp[0][0]=0;//
for(int i=1,len=strlen(s);i <= len;i++){
for(int j=0;j <= tot;j++){
for(int k=0;k<4;k++){
if(!trie[trie[j].son[k]].dan){
dp[i][trie[j].son[k]]=min(dp[i][trie[j].son[k]],dp[i-1][j]+(get(s[i-1])!=k));//dp[i][trie[j].son[k]]
}
}
}
}
int ret=INF;
for(int i=0,len=strlen(s);i <= tot;i++)
ret=min(ret,dp[len][i]);
return ret==INF?-1:ret;
}
int n,cas;
char s[N];
int main(){
while(scanf("%d",&n)==1&&n){
init();
while(n--){
scanf(" %s",s);
Insert(s);
}
build_ac();
scanf(" %s",s);
printf("Case %d: %d\n",++cas,Query(s));
}
return 0;
}
poj3691DNA repair
最新推荐文章于 2020-07-27 20:49:20 发布