hdu2457

AC自动机+DP

#include <cstdio>
#include <queue>
#include <cstring>
using namespace std;

#define D(x) 

const int MAX_D_LEN = 25;
const int MAX_LEN = 1005;
const int MAX_N = 55;
const int MAX_CHILD_NUM = 4;
const int MAX_NODE_NUM = MAX_N * MAX_D_LEN;
const int INF = 0x3f3f3f3f;

char dna[MAX_LEN];

struct Trie
{
    int next[MAX_NODE_NUM][MAX_CHILD_NUM];
    int fail[MAX_NODE_NUM];
    bool disease[MAX_NODE_NUM];
    int node_cnt;
    bool vis[MAX_NODE_NUM]; //set it to false
    int root;
    int dp[MAX_LEN][MAX_NODE_NUM];

    void init()
    {
        node_cnt = 0;
        root = newnode();
        memset(vis, 0, sizeof(vis));
    }

    int newnode()
    {
        for (int i = 0; i < MAX_CHILD_NUM; i++)
            next[node_cnt][i] = -1;
        disease[node_cnt++] = false;
        return node_cnt - 1;
    }

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

    void insert(char buf[])
    {
        int now = root;
        for (int i = 0; buf[i]; i++)
        {
            int id = get_id(buf[i]);
            if (next[now][id] == -1)
                next[now][id] = newnode();
            now = next[now][id];
        }
        disease[now] = true;
    }

    void build()
    {
        queue<int>Q;
        fail[root] = root;
        for (int i = 0; i < MAX_CHILD_NUM; i++)
            if (next[root][i] == -1)
                next[root][i] = root;
            else
            {
                fail[next[root][i]] = root;
                Q.push(next[root][i]);
            }
        while (!Q.empty())
        {
            int now = Q.front();
            Q.pop();
            for (int i = 0; i < MAX_CHILD_NUM; i++)
                if (next[now][i] == -1)
                    next[now][i] = next[fail[now]][i];
                else
                {
                    fail[next[now][i]]=next[fail[now]][i];
                    if (disease[fail[next[now][i]]])
                        disease[next[now][i]] = true;
                    Q.push(next[now][i]);
                }
        }
    }

    int work()
    {
        scanf("%s", dna);
        int len = strlen(dna);
        for (int i = 0; i < node_cnt; i++)
        {
            if (disease[i])
                dp[len][i] = INF;
            else
                dp[len][i] = 0;
        }
        for (int i = len - 1; i >= 0; i--)
        {
            int key = get_id(dna[i]);
            for (int j = 0; j < node_cnt; j++)
            {
                dp[i][j] = INF;
                if (disease[j])
                    continue;
                for (int k = 0; k < 4; k++)
                {
                    int temp = 1;
                    if (k == key)
                        temp = 0;
                    int v = next[j][k];
                    if (disease[v])
                        continue;
                    dp[i][j] = min(dp[i][j], temp + dp[i + 1][v]);
                    D(printf("%d\n", dp[i + 1][next[j][k]]));
                }
                D(printf("dp[%d][%d]=%d\n", i, j, dp[i][j]));
            }
        }
        return dp[0][root];
    }

    void debug()
    {
        for(int i = 0;i < node_cnt;i++)
        {
            printf("id = %3d,fail = %3d,end = %3d,chi = [",i,fail[i],disease[i]);
            for(int j = 0;j < MAX_CHILD_NUM;j++)
                printf("%2d",next[i][j]);
            printf("]\n");
        }
    }
}ac;

int n;
char st[MAX_D_LEN];

int main()
{
    int case_num = 1;
    while (scanf("%d", &n), n)
    {
        ac.init();
        for (int i = 0; i < n; i++)
        {
            scanf("%s", st);
            ac.insert(st);
        }
        ac.build();
        int ans = ac.work();
        if (ans >= INF)
            ans = -1;
        printf("Case %d: %d\n", case_num++, ans);
    }
    return 0;
}
View Code

 

posted @ 2015-03-24 20:13  金海峰  阅读(325)  评论(0编辑  收藏  举报