hdu2457

AC自动机+DP

hdu2457
#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

 

你可能感兴趣的:(HDU)