• HDU2457 DNA repair [AC自动机+DP]


      给出一个DNA串以及若干个带有疾病的串,问至少要改变DNA串中的几个字符,才能让它不携带病毒串。其实还是不包含若干子串的问题,可以转化为走一条不包含病毒串的路径,这条路径组成的串和给出DNA串最少相差几个字符,这样就很容易想到DP方程

      

      d[i][j]一开始初始化为无穷大,x是j的父亲节点,也就是说存在next[x][p]=j,一般都是从前向后刷表的。flag表示这一位和DNA串中的对应字符是否相等,相等时为0,不相等时为1。

      注意在走的过程中不要走到危险节点上去。

    #include <string.h>
    #include <stdio.h>
    #define MAXN 1001
    #define INF 0x3fffffff
    char s[MAXN];
    int n;
    int next[MAXN][4],fail[MAXN],flag[MAXN],pos;
    int calk(char c){
        if(c=='A')return 0;
        if(c=='G')return 1;
        if(c=='T')return 2;
        return 3;
    }
    int newnode(){
        for(int i=0;i<4;i++)next[pos][i]=0;
        fail[pos]=flag[pos]=0;
        return pos++;
    }
    void insert(char *s){
        int p=0;
        for(int i=0;s[i];i++){
            int k=calk(s[i]),&x=next[p][k];
            p=x?x:x=newnode();
        }
        flag[p]=1;
    }
    int q[MAXN],front,rear;
    void makenext(){
        q[front=rear=0]=0,rear++;
        while(front<rear){
            int u=q[front++];
            for(int i=0;i<4;i++){
                int v=next[u][i];
                if(v==0)next[u][i]=next[fail[u]][i];
                else q[rear++]=v;
                if(u&&v){
                    fail[v]=next[fail[u]][i];
                    if(flag[fail[v]])flag[v]=1;
                }
            }
        }
    }
    int d[2][MAXN],cal[MAXN];
    inline int min(int x,int y){return x<y?x:y;}
    int dp(char *s){
        int len=strlen(s),cur=0;
        for(int i=0;i<len;i++)d[0][i]=0;
        for(int i=0;i<pos;i++)cal[i]=0;
        //cal表示这个点是否计算过,没有计算过的点不进行遍历孩子操作
        d[0][0]=0,cal[0]=1;
        for(int i=0;i<len;i++){
            cur^=1;
            for(int u=0;u<pos;u++)d[cur][u]=INF;
            for(int u=0;u<pos;u++){
                if(!cal[u]||flag[u])continue;
                for(int k=0;k<4;k++){
                    int v=next[u][k];
                    if(flag[v])continue;
                    cal[v]=1;
                    d[cur][v]=min(d[cur][v],d[cur^1][u]+((calk(s[i])==k)?0:1));
                }
            }
        }
        int ans=INF;
        for(int u=0;u<pos;u++)ans=min(ans,d[cur][u]);
        return ans!=INF?ans:-1;
    }
    int main(){
        //freopen("test.in","r",stdin);
        int cas=1;
        while(scanf("%d",&n),n){
            pos=0;newnode();
            for(int i=0;i<n;i++){
                scanf("%s",s);
                insert(s);
            }
            makenext();
            scanf("%s",s);
            int ans=dp(s);
            printf("Case %d: %d\n",cas++,ans);
        }
        return 0;
    }
  • 相关阅读:
    USACO6.4-The Primes
    ZOJ2112--Dynamic Rankings (动态区间第k大)
    Havel定理
    HDU5107---K-short Problem (线段树区间 合并、第k大)
    POJ2104-- K-th Number(主席树静态区间第k大)
    poj2409 & 2154 polya计数+欧拉函数优化
    CodeForces
    HDU
    HDU
    Gym
  • 原文地址:https://www.cnblogs.com/swm8023/p/2626809.html
Copyright © 2020-2023  润新知