HDU 4534 郑厂长系列故事——新闻净化

  跟 HDU 4057 Rescue the Rabbit差不多的AC自动机+dp,比赛的时候被虐成傻逼了!!!

999的状态不多,直接状态压缩就行。dp[i][ACstatus][status] 到字符串第i位置,在AC自动机上状态为ACstatus,包含到999的状态为status。

更新了一下自动机的模板。。。Orz简洁写法

 

 

View Code
#include <iostream>
#include <cstdio>
#include <cmath>
#include <vector>
#include <cstring>
#include <algorithm>
#include <string>
#include <set>
#include <functional>
#include <numeric>
#include <sstream>
#include <stack>
#include <map>
#include <queue>

#define CL(arr, val)    memset(arr, val, sizeof(arr))
#define REP(i, n)       for((i) = 0; (i) < (n); ++(i))
#define FOR(i, l, h)    for((i) = (l); (i) <= (h); ++(i))
#define FORD(i, h, l)   for((i) = (h); (i) >= (l); --(i))
#define L(x)    (x) << 1
#define R(x)    (x) << 1 | 1
#define MID(l, r)   (l + r) >> 1
#define Min(x, y)   (x) < (y) ? (x) : (y)
#define Max(x, y)   (x) < (y) ? (y) : (x)
#define E(x)        (1 << (x))
#define iabs(x)     (x) < 0 ? -(x) : (x)
#define OUT(x)  printf("%lld\n", x)
#define Read()  freopen("data.in", "r", stdin)
#define Write() freopen("data.out", "w", stdout);

typedef long long LL;
const double eps = 1e-6;
const double PI = acos(-1.0);
const int inf = 0x1F1F1F1F;

using namespace std;

const int N = 1610;

struct node {
    int val;
    short type;
    bool cannot;
    short index;
    node *pre, *next[26];
    void init() {
        val = type = 0;
        index = cannot = 0;
        pre = NULL;
        memset(next, 0, sizeof(next));
    }
};

node trie[N];
node *root, *q[N];

int cnt, must;
int dp[2][N][1<<8];
int vv[2][N][1<<8];
char str[110];

void insert(node* root, char* str, int val) {
    int c, i;
    for(i = 0; str[i] != 0; ++i) {
        c = str[i] - 'a';
        if(root->next[c] == 0) {
            root->next[c] = &trie[++cnt];
            root->next[c]->init();
            root->next[c]->index = cnt;
        }
        root = root->next[c];
    }
    if(val == 999) {
        root->type |= (1<<must++);
    } else if(val == -999) {
        root->cannot = 1;
    } else {
        root->val += val;
    }
}

void buildAC() {
    int head, tail, i;
    node *u;
    root->pre = root;

    head = tail = 0;
    q[tail++] = root;

    while(head < tail) {
        u = q[head++];

        u->val += u->pre->val;
        u->type |= u->pre->type;
        u->cannot |= u->pre->cannot;

        for(i = 0; i < 26; ++i) {
            if(u->next[i] == 0) {
                if(u == root)   u->next[i] = root;
                else    u->next[i] = u->pre->next[i];
            } else {
                if(u == root)   u->next[i]->pre = root;
                else    u->next[i]->pre = u->pre->next[i];

                /*
                if(u->next[i]->pre->val)    u->next[i]->val += u->next[i]->pre->val;
                if(u->next[i]->pre->type)   u->next[i]->type |= u->next[i]->pre->type;
                if(u->next[i]->pre->cannot) u->next[i]->cannot = 1;
                */

                q[tail++] = u->next[i];
            }
        }
    }
}

void solve() {
    int i, j, k, c;
    int nxt, val, tt, n = strlen(str);

    CL(dp[1], 0x1f);
    CL(vv[1], 0);
    dp[1][0][0] = 0;
    vv[1][0][0] = 0;

    for(i = 0; i < n; ++i) {
        CL(dp[i&1], 0x1f);
        CL(vv[i&1], 0);
        for(j = 0; j <= cnt; ++j) {
            for(k = 0; k < (1<<must); ++k) {

                if(dp[(i+1)&1][j][k] >= inf)    continue;

                if(dp[i&1][j][k] > dp[(i+1)&1][j][k] + 1) {
                    dp[i&1][j][k] = dp[(i+1)&1][j][k] + 1;
                    vv[i&1][j][k] = vv[(i+1)&1][j][k];
                } else if(dp[i&1][j][k] == dp[(i+1)&1][j][k] + 1 && vv[i&1][j][k] < vv[(i+1)&1][j][k]) {
                    vv[i&1][j][k] = vv[(i+1)&1][j][k];
                }

                c = str[i] - 'a';
                nxt = trie[j].next[c]->index;
                if(trie[nxt].cannot)    continue;

                val = trie[nxt].val;
                tt = k|trie[nxt].type;

                if(dp[i&1][nxt][tt] > dp[(i+1)&1][j][k]) {
                    dp[i&1][nxt][tt] = dp[(i+1)&1][j][k];
                    vv[i&1][nxt][tt] = vv[(i+1)&1][j][k] + val;
                } else if( dp[i&1][nxt][tt] == dp[(i+1)&1][j][k] &&
                     vv[i&1][nxt][tt] < vv[(i+1)&1][j][k] + val) {
                    vv[i&1][nxt][tt] = vv[(i+1)&1][j][k] + val;
                }
            }
        }
    }
    int ans1 = inf, ans2 = 0, full = (1<<must) - 1;
    for(j = 0; j <= cnt; ++j) {
        if(ans1 > dp[(n-1)&1][j][full]) {
            ans1 = dp[(n-1)&1][j][full];
            ans2 = vv[(n-1)&1][j][full];
        }
        if(ans1 == dp[(n-1)&1][j][full] && ans2 < vv[(n-1)&1][j][full]) {
            ans2 = vv[(n-1)&1][j][full];
        }
    }
    if(ans1 == inf)     puts("Banned");
    else    printf("%d %d\n", ans1, ans2);
}

int main() {
    //freopen("data.in", "r", stdin);

    int T, n, g, cas = 0;
    scanf("%d", &T);
    while(T--) {
        root = &trie[0];
        root->init();
        cnt = must = 0;
        scanf("%d", &n);
        while(n--) {
            scanf("%s %d", str, &g);
            insert(root, str, g);
        }
        buildAC();
        scanf("%s", str);
        printf("Case %d: ", ++cas);
        solve();
    }
    return 0;
}

 

posted @ 2013-04-01 15:34  AC_Von  阅读(423)  评论(0编辑  收藏  举报