|
#include <iostream>
#include <math.h>
using namespace std;

const int MAXN=20*55;
const int MAXL=1005;
const int K=4;// kind of child
int dp[MAXL][MAXN];

struct Node
  {
Node *next[K], *fail;
int flag, id; // use for T[j].next[k]->id
void Init(int index)
 {
id=index;
flag=0;
fail=NULL;
for(int i=0; i<K; i++)next[i]=NULL;
}
}* Q[MAXN/2], *root, T[MAXN];// Q for queue, root&T for tree;

int index=0;
Node * newNode()
  {
T[index].Init(index);
return &T[index++];
}

int tokind(char k)
  {
if(k=='A')return 0;
else if(k=='C')return 1;
else if(k=='G')return 2;
else return 3;
}

void insert(char *str)
  {
if(root==NULL)
root=newNode();

Node *now=root;
for(int i=0; str[i]; i++)
 {
int kind=tokind(str[i]);
if(now->next[kind]==NULL)
now->next[kind]=newNode();
now=now->next[kind];
}
now->flag=1;
}

int search(Node *p)
  {
while(p!=root)
 {
p=p->fail;
if(p->flag)return 1;
}
return 0;
}

void buildAC()
  {
int head=0, tail=0;
root->fail=NULL;

Q[tail++]=root;
while(head<tail)
 {
Node *now=Q[head++];
if(now->flag==0)now->flag=search(now);
for(int i=0; i<K; i++)
 {
if(now->next[i]!=NULL)
 {
if(now==root)
now->next[i]->fail=root;
else
now->next[i]->fail=now->fail->next[i];
Q[tail++]=now->next[i];
}
else
 {
if(now==root)
now->next[i]=root;
else
now->next[i]=now->fail->next[i];
}
}
}
}

 void update(int &a, int b) {if(a==-1||b<a)a=b;}

int slove(char *str)
  {
memset(dp, -1, sizeof(dp));
dp[0][0]=0;
Node *p=root;

for(int i=0; str[i]; i++)
 {
for(int j=0; j<index; j++)
 {
if(dp[i][j]!=-1&&T[j].flag==0)
 {
int kind=tokind(str[i]);
for(int k=0; k<K; k++)// need to match (k, kind)
 {
Node *chd=T[j].next[k];
if(chd->flag==0)
update(dp[i+1][chd->id],dp[i][j]+(k!=kind));
}
}
}
}
int len=strlen(str);
int res=-1;
for(int ii=0; ii<index; ii++)
if(dp[len][ii]!=-1)update(res, dp[len][ii]);
return res;
}

int main()
  {
freopen ("in.txt", "r", stdin);
int N, Tcase=0;
while(scanf("%d", &N)!=EOF&&N)
 {
root=NULL;
index=0;
for(int i=0; i<N; i++)
 {
char s[25];
scanf("%s", s);
insert(s);
}
buildAC();
char ss[1005];
scanf("%s", ss);
printf("Case %d: %d\n", ++Tcase, slove(ss));
}
return 0;
}

|