hdu 4057 AC自动机

题目链接http://acm.hdu.edu.cn/showproblem.php?pid=4057

自动机上的dp

/*
hdu 4057
*/
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <cmath>
#include <cctype>
#include <vector>
#include <bitset>
#include <stack>
#include <queue>
#include <map>
#include <algorithm>
#include <iostream>
#include <string>
#include <set>
#define X first
#define Y second
#define sqr(x) (x)*(x)
#pragma comment(linker,"/STACK:102400000,102400000")
using namespace std;
const double PI = acos(-1.0);
map<int, int>::iterator it;
typedef long long LL ;
template<typename T> void checkmin(T &x, T y) {x = min(x, y);}
template<typename T> void checkmax(T &x, T y) {x = max(x, y);}

const int MAX_NODE = 1005;
const int CHILD_NUM = 4;
const int inf = 1e6;
int dp[2][MAX_NODE][1<<10];
int n, L;
int w[11];
class ACAutomaton {
    public:
        int chd[MAX_NODE][CHILD_NUM];
        int fail[MAX_NODE];
        int Q[MAX_NODE];
        int val[MAX_NODE];
        int ID[256];
        int sz;
        void Init() {
            ID['A'] = 0;
            ID['G'] = 1;
            ID['T'] = 2;
            ID['C'] = 3;
        }
        void Reset() {
            fail[0] = 0;
            memset(chd[0], 0, sizeof(chd[0]));
            sz = 1;
        }
        void Insert(char *s, int k) {
            int q = 0;
            for(; *s; ++s) {
                int c = ID[*s];
                if(!chd[q][c]) {
                    memset(chd[sz], 0, sizeof(chd[sz]));
                    val[sz] = 0;
                    chd[q][c] = sz++;
                }
                q = chd[q][c];
            }
            val[q] |= 1 << k;
        }
        void Construct() {
            int *s = Q, *e = Q;
            for(int i = 0; i < CHILD_NUM; ++i) {
                if(chd[0][i]) {
                    *e++ = chd[0][i];
                    fail[ chd[0][i] ] = 0;
                }
            }
            while(s != e) {
                int r = *s++;
                for(int i = 0; i < CHILD_NUM; ++i) {
                    int &u = chd[r][i];
                    int v = fail[r];
                    if(u) {
                        *e++ = u;
                        fail[u] = chd[v][i];
                        val[u] |= val[ fail[u] ];
                    }
                    else u = chd[v][i];
                }
            }
        }
        int Get_dp() {
            int st = 0, ed = 1;
            for(int i = 0; i < sz; ++i)for(int j = 0; j < (1 << n); ++j)dp[st][i][j]=dp[ed][i][j] = -inf;
            dp[0][0][0] = 0;
            for(int i = 0; i < L; ++i) {
                for(int j = 0; j < sz; ++j) {
                    for(int mask = 0; mask < (1 << n); ++mask) {
                        if(dp[st][j][mask] > -inf) {
                            for(int k = 0; k < CHILD_NUM; ++k) {
                                int q = chd[j][k];
                                int qmask = val[q];
                                int pmask = (qmask ^ mask)&qmask;
                                int add = 0;
                                for(int p = 0; p < n; ++p) {
                                    if((pmask >> p) & 1) {
                                        add += w[p];
                                    }
                                }
                                checkmax(dp[ed][q][pmask|mask], dp[st][j][mask] + add);
                            }
                        }
                    }
                }
                for(int j = 0; j < sz; ++j)for(int k = 0; k < (1 << n); ++k)dp[st][j][k] = -inf;
                st ^= 1, ed ^= 1;
            }
            int res = -inf;
            for(int i = 0; i < sz; ++i) {
                for(int j = 0; j < (1 << n); ++j) {
                    res = max(res, dp[st][i][j]);
                }
            }
            return res;
        }
} AC;

char s[105];
int main() {
    AC.Init();
    while(~scanf("%d%d", &n, &L)) {
        AC.Reset();
        for(int i = 0; i < n; ++i) {
            scanf("%s %d", s, w + i);
            AC.Insert(s, i);
        }
        AC.Construct();
        int res = AC.Get_dp();
        if(res < 0) {
            puts("No Rabbit after 2012!");
        }
        else {
            printf("%d\n", res);
        }
    }
    return 0;
}

  

posted @ 2013-11-04 13:16  degree  阅读(110)  评论(0编辑  收藏  举报