您的位置:首页 > 其它

poj3691(ac自动机+dp)

2016-06-17 20:46 357 查看
链接:点击打开链接

题意:给一个母串,和n个子串问最少修改几个字母能使母串不含任何一个子串,如果不能输出-1

代码:#include <set>
#include <map>
#include <queue>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <iostream>
#include <algorithm>
using namespace std;
const int INF=0x3f3f3f3f;
char tt[]="AGCT";
char S[1005];
int n,rt,len,dp[1005][1005];
struct node{
int c[4],dis,fail;
}s[1005];
int get(char c){
int i;
for(i=0;i<4;i++)
if(tt[i]==c)
return i;
}
void in(char ss[]){
int i,u;
u=0;
for(i=0;ss[i];i++){
if(s[u].c[get(ss[i])]==0)
s[u].c[get(ss[i])]=rt++;
u=s[u].c[get(ss[i])];
}
s[u].dis=1;
}
void getfail(){
int i,u,v,tmp;
queue<int> qu;
qu.push(0);
while(qu.size()){
u=qu.front();
qu.pop();
for(i=0;i<4;i++){
if(v=s[u].c[i]){
if(u==0)
s[v].fail=0;
else{
tmp=s[u].fail;
while(tmp&&s[tmp].c[i]==0)
tmp=s[tmp].fail;
s[v].fail=s[tmp].c[i];
s[v].dis|=s[s[tmp].c[i]].dis;
}
qu.push(v);
}
else
s[u].c[i]=s[s[u].fail].c[i];
}
}
}
int ac(){
int i,j,k,ans,tmp;
memset(dp,INF,sizeof(dp));
dp[0][0]=0;
getfail();
for(i=0;i<len;i++){ //dp[i][j]表示长度是i,走到j节点,最小修改的次数
for(j=0;j<rt;j++){ //遇到带标记的节点直接不转移即可
if(dp[i][j]>=INF)
continue; //跟bzoj1030基本是一样的
for(k=0;k<4;k++){
if(s[s[j].c[k]].dis)
continue;
tmp=dp[i+1][s[j].c[k]];
if(S[i+1]==tt[k])
tmp=min(tmp,dp[i][j]);
else
tmp=min(tmp,dp[i][j]+1);
dp[i+1][s[j].c[k]]=tmp;
}
}
}
ans=INF;
for(i=0;i<rt;i++)
ans=min(ans,dp[len][i]);
if(ans>=INF)
ans=-1;
return ans;
}
int main(){
int i,j,cas;
cas=1;
while(scanf("%d",&n)!=EOF&&n){
rt=1;
memset(s,0,sizeof(s));
for(i=0;i<n;i++){
scanf("%s",S);
in(S);
}
scanf("%s",S+1);
len=strlen(S+1);
printf("Case %d: %d\n",cas++,ac());
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: