hdu 2457 DNA repair(AC自动机+DP)

来源:互联网 发布:剑灵灵族女萌萌的数据 编辑:程序博客网 时间:2024/06/08 09:31

题意:给出n个串,现在有个长串,可以修改这个串的任意位置,要求这个串不包含这n个串,问最小修改次数。

思路:首先构建AC自动机,用dp[i][j]表示长度为i的串,现在在状态j时最小要修改的次数,每次对于ATCG四个字符,如果状态可以发生转移,那么状态转移方程为dp[i+1][u]=min(dp[i+1][u],dp[i][j]+(c!=indx(str[i])));


代码:


#include<iostream>#include<cstdio>#include<cstring>#include<string>#include<algorithm>#include<map>#include<queue>#include<set>#include<stack>#include<cmath>#include<vector>#define inf 0x3f3f3f3f#define Inf 0x3FFFFFFFFFFFFFFFLL#define eps 1e-9#define pi acos(-1.0)using namespace std;typedef long long ll;const int maxn=1000+10;int ch[maxn][4],next[maxn],flag[maxn],size;void Init(){    memset(ch[0],0,sizeof(ch[0]));    memset(next,0,sizeof(next));    size=0;flag[0]=0;}int indx(char c){    if(c=='A') return 0;    if(c=='T') return 1;    if(c=='C') return 2;    return 3;}void Insert(const char *s){    int u=0,n=strlen(s);    for(int i=0;i<n;++i)    {        int c=indx(s[i]);        if(!ch[u][c])        {            ch[u][c]=++size;            memset(ch[size],0,sizeof(ch[size]));            flag[size]=0;        }        u=ch[u][c];    }    flag[u]=1;}void build(){    queue<int>q;    for(int c=0;c<4;++c)        if(ch[0][c]) q.push(ch[0][c]);    int r,u,v;    while(!q.empty())    {        r=q.front();q.pop();        for(int c=0;c<4;++c)        {            u=ch[r][c];            if(!u) {ch[r][c]=ch[next[r]][c];continue;}            q.push(u);            v=next[r];            while(v&&!ch[v][c]) v=next[v];            next[u]=ch[v][c];            flag[u]|=flag[next[u]];        }    }}char str[maxn];int dp[maxn][maxn];int solve(){    int n=strlen(str);    memset(dp,0xff,sizeof(dp));    dp[0][0]=0;    int u;    for(int i=0;i<n;++i)        for(int j=0;j<=size;++j)        {            if(flag[j]||dp[i][j]==-1) continue;            for(int c=0;c<4;++c)            {                u=ch[j][c];                if(flag[u]) continue;                if(dp[i+1][u]==-1) dp[i+1][u]=dp[i][j]+(c!=indx(str[i]));                else dp[i+1][u]=min(dp[i+1][u],dp[i][j]+(c!=indx(str[i])));            }        }    int ans=inf;    for(int i=0;i<=size;++i)        if(dp[n][i]!=-1) ans=min(ans,dp[n][i]);    if(ans==inf) return -1;    return ans;}int main(){    //freopen("in.txt","r",stdin);    //freopen("out.txt","w",stdout);    int tcase=0,n;    while(~scanf("%d",&n))    {        if(n==0) break;        Init();        tcase++;        for(int i=0;i<n;++i)        {            scanf("%s",str);            Insert(str);        }        build();        scanf("%s",str);        printf("Case %d: %d\n",tcase,solve());    }    return 0;}


0 0
原创粉丝点击