UVA 1399 Puzzle 求一个最长的串使得该串不包含任何禁止串为子串 AC自动机 + DP +dfs判环

来源:互联网 发布:安卓防沉迷软件 编辑:程序博客网 时间:2024/05/17 16:44

【解题参考blog】http://blog.csdn.net/acm_10000h/article/details/48878645

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

【解题方法】实际上就是Trie图上的最长路,先对模式串建立AC自动机,之后在AC自动机上跑最长路。无限长的情况就是trie图形成了环,这个dfs判环即可!

【代码君】

////Created by just_sort 2016/10/13//Copyright (c) 2016 just_sort.All Rights Reserved//#include <set>#include <map>#include <queue>#include <stack>#include <cmath>#include <cstdio>#include <cstdlib>#include <cstring>#include <iostream>#include <algorithm>using namespace std;typedef long long LL;const int maxn = 55555;const int maxm = 26;struct Acautomata{    int ch[maxn][maxm],val[maxn],fail[maxn],root,sz;    int newnode(){        val[sz] = 0;        memset(ch[sz], 0, sizeof(ch[sz]));        return sz++;    }    void init(){        sz = 0;        root = newnode();    }    void insert(char *s,int v){        int len = strlen(s);        int u = root;        for(int i = 0; i < len; i++){            int now = s[i] - 'A';            if(!ch[u][now]){                ch[u][now] = newnode();            }            u = ch[u][now];        }        val[u] = v;    }    void build(){        queue <int> q;        fail[0] = 0;        for(int i = 0; i < maxm; i++){            int u = ch[0][i];            if(u){                q.push(u);                fail[u] = 0;            }        }        while(q.size())        {            int u = q.front(); q.pop();            for(int i = 0; i < maxm; i++){                int v = ch[u][i];                if(!v){                    ch[u][i] = ch[fail[u]][i]; continue;                }                q.push(v);                int j = fail[u];                while(j && !ch[j][i]) j = fail[j];                fail[v] = ch[j][i];                val[v] |= val[fail[v]];            }        }    }}ac;int n,m;int vis1[maxn],vis2[maxn],dp[maxn],path[maxn][2];bool dfs1(int u){    vis2[u] = 1;    for(int i = 0; i < n; i++)    {        int v = ac.ch[u][i];        if(vis1[v]) return 1;        if(!vis2[v] && !ac.val[v])        {            vis1[v] = 1;            if(dfs1(v)) return true;            vis1[v] = 0;        }    }    return false;}int dfs2(int u){    if(vis1[u]) return dp[u];    vis1[u] = 1;    dp[u] = 0;    for(int i = n - 1; i >= 0; i--)    {        if(!ac.val[ac.ch[u][i]])        {            int tmp = dfs2(ac.ch[u][i]) + 1;            if(dp[u] < tmp)            {                dp[u] = tmp;                path[u][0] = ac.ch[u][i];                path[u][1] = i;            }        }    }    return dp[u];}void print_path(int u){    if(path[u][0] == -1) return ;    printf("%c", 'A' + path[u][1]);    print_path(path[u][0]);}int main(){    int T;    scanf("%d",&T);    while(T--)    {        ac.init();        scanf("%d%d",&n,&m);        for(int i = 0; i < m; i++){            char op[55];            scanf("%s",op);            ac.insert(op,1);        }        ac.build();        memset(vis1, 0, sizeof(vis1));        memset(vis2, 0, sizeof(vis2));        vis1[0] = 1;        if(dfs1(0))        {            printf("No\n");        }        else{            memset(vis1, 0, sizeof(vis1));            memset(path, -1, sizeof(path));            if(dfs2(0) == 0)            {                printf("No\n");            }            else            {                print_path(0);                puts("");            }        }    }    return 0;}


0 0
原创粉丝点击