uva 1399 - Puzzle(AC自动机)

来源:互联网 发布:日本经济数据2016 编辑:程序博客网 时间:2024/05/23 01:21

题目链接:uva 1399 - Puzzle

题目大意:给定K和N,表示有K种不同的字符,N个禁止串,求一个最长的串使得该串不包含任何禁止串为子串。如果存在循环或者不能构成的话,输出No。

解题思路:建立AC自动机,然后在AC自动机上做dp,所有单词结尾节点为禁止点。

#include <cstdio>#include <cstring>#include <queue>#include <algorithm>using namespace std;const int maxn = 50005;const int sigma_size = 26;struct Aho_Corasick {    int sz, ac[maxn][sigma_size];    int fail[maxn], last[maxn];    void init();    int idx(char ch);    void insert(char* s);    void get_fail();}fuck;int K, vis[maxn], dp[maxn], jump[maxn];int dfs (int u) {    if (vis[u])        return -1;    if (dp[u] != -1)        return dp[u];    vis[u] = 1;    int& ret = dp[u];    jump[u] = -1;    ret = 0;    for (int i = K - 1; i >= 0; i--) {        int v = fuck.ac[u][i];        if (fuck.last[v] == 0) {            int tmp = dfs(v);            if (tmp == -1)                return -1;            if (tmp + 1 > ret) {                ret = tmp + 1;                jump[u] = i;            }        }    }    vis[u] = 0;    return ret;}void put_ans (int u) {    while (jump[u] != -1) {        printf("%c", 'A' + jump[u]);        u = fuck.ac[u][jump[u]];    }    printf("\n");}int main () {    int cas, n;    char word[55];    scanf("%d", &cas);    while (cas--) {        fuck.init();        memset(vis, 0, sizeof(vis));        memset(dp, -1, sizeof(dp));        scanf("%d%d", &K, &n);        for (int i = 0; i < n; i++) {            scanf("%s", word);            fuck.insert(word);        }        fuck.get_fail();        if (dfs(0) != -1 && dp[0])            put_ans(0);        else            printf("No\n");    }    return 0;}void Aho_Corasick::init() {    sz = 1;    memset(ac[0], 0, sizeof(ac[0]));}int Aho_Corasick::idx(char ch) {    return ch - 'A';}void Aho_Corasick::insert(char* s) {    int n = strlen(s), u = 0;    for (int i = 0; i < n; i++) {        int v = idx(s[i]);        if (ac[u][v] == 0) {            memset(ac[sz], 0, sizeof(ac[sz]));            last[sz] = 0;            ac[u][v] = sz++;        }        u = ac[u][v];    }    last[u] = 1;}void Aho_Corasick::get_fail () {    queue<int> que;    fail[0] = 0;    for (int i = 0; i < sigma_size; i++) {        int u = ac[0][i];        if (u) {            fail[u] = 0;            que.push(u);        }    }    while (!que.empty()) {        int r = que.front();        que.pop();        for (int i = 0; i < K; i++) {            int u = ac[r][i];            if (u == 0) {                ac[r][i] = ac[fail[r]][i];                continue;            }            que.push(u);            int v = fail[r];            while (v && ac[v][i] == 0)                v = fail[v];            fail[u] = ac[v][i];            last[u] |= last[fail[u]];        }    }}
1 0
原创粉丝点击