您的位置:首页 > 大数据 > 人工智能

POJ3691:DNA repair(AC自动机+DP)

2018-03-08 15:19 423 查看
题面

题意:有很多个只包含4个字母的短串和一个长串

问长串至少改几个字符就不包含任何短串

用短串建AC自动机,标记好所有结束状态

设f[i][j]f[i][j]为长度为i,后缀为状态j的最小更改数

每次枚举4个字母转移就可以了

#include <iostream>
#include <fstream>
#include <algorithm>
#include <cmath>
#include <ctime>
#include <cstdio>
#include <cstdlib>
#include <cstring>

using namespace std;
#define mmst(a, b) memset(a, b, sizeof(a))
#define mmcp(a, b) memcpy(a, b, sizeof(b))

typedef long long LL;

const int N=2020;

int n,len,ans,Violet;
int son
[4],fail
,cnt;
bool ed
;
int q
;
int f

;
char s
;

int ch(char cc)
{
if(cc=='A')
return 0;
if(cc=='C')
return 1;
if(cc=='T')
return 2;
return 3;
}

int main()
{
while(1)
{

cin>>n;
if(n==0)
return 0;
Violet++;

cnt=1;
mmst(ed,0);
for(int i=0;i<N;i++)
for(int j=0;j<4;j++)
son[i][j]=0;
ans=1001;

for(int i=1;i<=n;i++)
{
int now=1;
scanf("%s",s+1);
len=strlen(s+1);
for(int j=1;j<=len;j++)
{
if(!son[now][ch(s[j])])
son[now][ch(s[j])]=++cnt;
now=son[now][ch(s[j])];
}
ed[now]=1;
}

int hh=1,tt=1;
fail[1]=q[1]=1;
while(hh<=tt)
{
int hy=q[hh++];
for(int i=0;i<4;i++)
if(son[hy][i])
{
q[++tt]=son[hy][i];
fail[son[hy][i]]= (hy==1) ? 1 : son[fail[hy]][i];
ed[son[hy][i]]|=ed[fail[son[hy][i]]];
}
else
son[hy][i]= (hy==1) ? 1 : son[fail[hy]][i];
}

scanf("%s",s+1);
len=strlen(s+1);

for(int i=0;i<=len;i++)
for(int j=1;j<=cnt;j++)
f[i][j]=1001;

f[0][1]=0;
for(int i=1;i<=len;i++)
for(int j=1;j<=cnt;j++)
for(int k=0;k<4;k++)
if(!ed[son[j][k]])
f[i][son[j][k]]=min(f[i][son[j][k]],f[i-1][j]+ ((ch(s[i])==k) ? 0 : 1));

for(int j=1;j<=cnt;j++)
ans=min(ans,f[len][j]);

cout<<"Case "<<Violet<<": "<<((ans!=1001) ? ans : -1)<<endl;
}

return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: