DNA repair - HDU 2457(自动机+dp)

题目大意:给你N个DNA的串,也就是至包含'A','T','G','C'四种碱基的,这些给定的串都是带有遗传病的,然后给你一个不会超过1000的串,问你至少几个地方才能让这个串不包含遗传病,如果不论怎么修改都没用,输出'-1'

 

分析:用dp[Ni][nNode],表示长度为i时候到达第n个节点修改的最小次数,然后统计最后一层次最小次数就行了。

 

代码如下:

=============================================================================================================================

#include<iostream>
#include<algorithm>
#include<stdio.h>
#include<string.h>
#include<queue>
using namespace std;

const int MAXN = 1007;
const int MAXM = 57;
const int MaxSon = 4;
const int oo = 1e9+7;

int dp[MAXN][MAXN];

struct Ac_Trie
{
    int next[MAXN][MaxSon];
    int Fail[MAXN], End[MAXN];
    int cnt, root;

    int newnode()
    {
        for(int i=0; i<MaxSon; i++)
            next[cnt][i] = -1;
        Fail[cnt] = End[cnt] = false;

        return cnt++;
    }
    void InIt()
    {
        cnt = 0;
        root = newnode();
    }
    int Find(char ch)
    {
        if(ch == 'A')return 0;
        if(ch == 'T')return 1;
        if(ch == 'G')return 2;

        return 3;
    }
    void Insert(char s[])
    {
        int now = root;

        for(int i=0; s[i]; i++)
        {
            int k = Find(s[i]);

            if(next[now][k] == -1)
                next[now][k] = newnode();
            now = next[now][k];
        }

        End[now] = true;
    }
    void GetFial()
    {
        queue<int>Q;
        int now = root;

        for(int i=0; i<MaxSon; i++)
        {
            if(next[now][i] == -1)
                next[now][i] = root;
            else
            {
                Fail[next[now][i]] = root;
                Q.push(next[now][i]);
            }
        }

        while(Q.size())
        {
            now = Q.front();
            Q.pop();

            for(int i=0; i<MaxSon; i++)
            {
                if(next[now][i] == -1)
                    next[now][i] = next[Fail[now]][i];
                else
                {
                    Fail[next[now][i]] = next[Fail[now]][i];
                    Q.push(next[now][i]);
                }
            }

            End[now] |= End[Fail[now]];
        }
    }
};
Ac_Trie ac;


int main()
{
    int N, t=1;

    while(scanf("%d", &N), N)
    {
        char s[MAXN];
        ac.InIt();

        for(int i=0; i<N; i++)
        {
            scanf("%s", s);
            ac.Insert(s);
        }
        ac.GetFial();

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

        for(int i=0; i<=N; i++)
        for(int j=0; j<ac.cnt; j++)
            dp[i][j] = oo;

        dp[0][0] = 0;

        for(int i=0; i<N-1; i++)
        for(int j=0; j<ac.cnt; j++)
        for(int k=0; k<4; k++)
        {
            int w = dp[i][j];
            int next = ac.next[j][k];

            if(ac.End[next])continue;

            if(ac.Find(s[i+1]) != k)
                w++;

            if(dp[i+1][next] > w)
                dp[i+1][next] = w;
        }

        int Min = oo;

        for(int i=0; i<ac.cnt; i++)
            Min = min(Min, dp[N-1][i]);

        if(Min == oo)
            Min = -1;

        printf("Case %d: %d\n", t++, Min);
    }

    return 0;
}

 

posted @ 2015-08-26 14:21  无忧望月  阅读(135)  评论(0编辑  收藏  举报
levels of contents