HDU 2457

直接从root遍历扩展DP,当扩展到的字母和字符串字母相同时,不用修改,不同时,要求修改加1

注意不要扩展危险结点。

#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <climits>
#include <string.h>
#include <queue>
#include <cmath>
#include <map>
#include <vector>
#define LL  __int64
using namespace std;

const int Maxn=1010;
const int dictsize=4;
const int root=0;
const int inf=(1<<30);
int ids['Z'];
int fail[Maxn],trie[Maxn][dictsize];
bool tag[Maxn];
int head,tail,tot;
int que[Maxn];
char str[Maxn];
int n;
int dp[Maxn][Maxn];

void Insert_trie(){
	int p=0,i=0,index;
	while(str[i]){
		index=ids[str[i]];
		if(trie[p][index]==-1) trie[p][index]=++tot;
		p=trie[p][index];
		i++;
	}
	tag[p]=true;
}

void build_ac(){
	head=tail=0;
	que[tail++]=root;
	while(head!=tail){
		int tmp=que[head++];
		int p=-1;
		for(int i=0;i<dictsize;i++){
			if(trie[tmp][i]!=-1){
				if(tmp==root) fail[trie[tmp][i]]=root;
				else{
					p=fail[tmp];
					while(p!=-1){
						if(trie[p][i]!=-1){
							fail[trie[tmp][i]]=trie[p][i];
							break;
						}
						p=fail[p];
					}
					if(p==-1) fail[trie[tmp][i]]=root;
				}
				if(tag[fail[trie[tmp][i]]]) tag[trie[tmp][i]]=true;
				que[tail++]=trie[tmp][i];
			}
			else{	//trie[tmp][i]==-1
				if(tmp==root) trie[tmp][i]=root;
				else{
					p=fail[tmp];
					while(p!=-1){
						if(trie[p][i]!=-1){
							trie[tmp][i]=trie[p][i];
							break;
						}
						p=fail[p];
					}
					if(p==-1) trie[tmp][i]=root;
				}
			}
		}
	}
}

int main(){
	int T=0;
	ids['A']=0,ids['C']=1,ids['G']=2,ids['T']=3;
	while(scanf("%d",&n)&&n){
		head=tail=tot=0;
		memset(fail,-1,sizeof(fail));
		memset(trie,-1,sizeof(trie));
		memset(tag,false,sizeof(tag));
		for(int i=0;i<n;i++){
			scanf("%s",str);
			Insert_trie();
		}
		scanf("%s",str+1);
		build_ac();
		int len=strlen(str+1);
		memset(dp,-1,sizeof(dp));
		dp[0][0]=0; int son;
		for(int j=0;j<len;j++){
			for(int i=0;i<=tot;i++){
				if(dp[i][j]>=0){
					for(int k=0;k<dictsize;k++){
						if(!tag[trie[i][k]]){
							son=trie[i][k];
							if(k==ids[str[j+1]]){
								if(dp[son][j+1]==-1){
									dp[son][j+1]=dp[i][j];
								}
								else{
									dp[son][j+1]=min(dp[i][j],dp[son][j+1]);
								}
							}
							else{
								if(dp[son][j+1]==-1){
									dp[son][j+1]=dp[i][j]+1;
								}
								else{
									dp[son][j+1]=min(dp[i][j]+1,dp[son][j+1]);
								}
							}
						}
					}
				}
			}
		}
		int ans=inf;
		for(int i=0;i<=tot;i++){
			if(dp[i][len]!=-1){
				ans=min(ans,dp[i][len]);
			}
		}
		printf("Case %d: %d\n",++T,ans==inf?-1:ans);
	}
	return 0;
}

  

posted @ 2015-03-03 21:19  chenjunjie1994  阅读(120)  评论(0编辑  收藏  举报