• bzoj2938 AC自动机 + 拓扑排序找环


    https://www.lydsy.com/JudgeOnline/problem.php?id=2938

    题意:给出N个01病毒序列,询问是否存在一个无限长的串不存在病毒序列

    正常来说,想要寻找一个串是否出现这些01序列可以直接跑AC自动机,这题反向问有没有无限长的不出现,说明在AC自动机上询问的时候,要避免经过所有病毒串标记的end结点以及需要寻找一个可以无限跑的环。

    所以我们将字典树的边和失配指针的边都看作是一条有向边,如果存在一个环上没有病毒结尾的标记,那么他就是合法的。

    值得一提的是,fail指针的意义是指向最长公共前后缀的下一个结点,因此如果一个节点的fail指针指向了一个危险结点,则这个结点也是危险的,因为他指向的点一定是他的后缀。

    #include <map>
    #include <set>
    #include <ctime>
    #include <cmath>
    #include <queue>
    #include <stack>
    #include <vector>
    #include <string>
    #include <cstdio>
    #include <cstdlib>
    #include <cstring>
    #include <sstream>
    #include <iostream>
    #include <algorithm>
    #include <functional>
    using namespace std;
    inline int read(){int now=0;register char c=getchar();for(;!isdigit(c);c=getchar());
    for(;isdigit(c);now=now*10+c-'0',c=getchar());return now;}
    #define For(i, x, y) for(int i=x;i<=y;i++)  
    #define _For(i, x, y) for(int i=x;i>=y;i--)
    #define Mem(f, x) memset(f,x,sizeof(f))  
    #define Sca(x) scanf("%d", &x)
    #define Sca2(x,y) scanf("%d%d",&x,&y)
    #define Sca3(x,y,z) scanf("%d%d%d",&x,&y,&z)
    #define Scl(x) scanf("%lld",&x);  
    #define Pri(x) printf("%d
    ", x)
    #define Prl(x) printf("%lld
    ",x);  
    #define CLR(u) for(int i=0;i<=N;i++)u[i].clear();
    #define LL long long
    #define ULL unsigned long long  
    #define mp make_pair
    #define PII pair<int,int>
    #define PIL pair<int,long long>
    #define PLL pair<long long,long long>
    #define pb push_back
    #define fi first
    #define se second 
    typedef vector<int> VI;
    const double eps = 1e-9;
    const int maxn = 5e4 + 10;
    const int INF = 0x3f3f3f3f;
    const int mod = 1e9 + 7; 
    int N,M,K;
    vector<int>Q[maxn];
    int a[maxn];
    struct AC{
        int next[2000010][2],fail[2000010];
        int end[2000010],ind[2000010];;
        int root,tot;
        int newnode(){
            next[tot][0] = next[tot][1] = -1;
            end[tot] = 0; ind[tot] = 0;
            return tot++;
        }
        void init(){
            tot = 0;
            root = newnode();
        }
        void insert(char *str){
            int p = root;
            for(int i = 0;str[i]; i ++){
                int id = str[i] - '0';
                if(next[p][id] == -1) next[p][id] = newnode();
                p = next[p][id];
            }
            end[p] = 1;
        }
        void Build(){
            queue<int>Q;
            for(int i = 0 ; i < 2; i ++){
                if(next[root][i] != -1){
                    fail[next[root][i]] = root;
                    Q.push(next[root][i]);
                }else{
                    next[root][i] = root;
                }
            }
            while(!Q.empty()){
                int u = Q.front(); Q.pop();
                for(int i = 0 ; i < 2; i ++){
                    if(next[u][i] == -1){
                        next[u][i] = next[fail[u]][i];
                    }else{
                        fail[next[u][i]] = next[fail[u]][i];
                        if(end[fail[next[u][i]]]){
                            end[next[u][i]] = 1;
                        }
                        Q.push(next[u][i]);
                    }
                }
            }
        }
        bool solve(){
            for(int i = 0 ; i < tot; i ++){
                if(end[i]) continue;
                ind[next[i][0]]++;
                ind[next[i][1]]++;
            }
            queue<int>Q;
            for(int i = 0 ; i < tot; i ++){
                if(!end[i] && !ind[i]) Q.push(i);
            }
            while(!Q.empty()){
                int u = Q.front(); Q.pop();
                for(int i = 0 ; i < 2; i ++){
                    ind[next[u][i]]--;
                    if(!end[next[u][i]] && !ind[next[u][i]]) 
                        Q.push(next[u][i]);
                }
            }
            for(int i = 0 ; i < tot; i ++){
                if(!end[i] && ind[i]) return true;
            }
            return false;    
        }
    }ac;
    char str[maxn];
    int main(){
        Sca(N);
        ac.init();
        For(i,1,N){
            scanf("%s",str);
            ac.insert(str);
        }
        ac.Build();
        if(ac.solve()) puts("TAK");
        else puts("NIE");
        return 0;
    }
  • 相关阅读:
    Linux下面编译安装ffmpeg
    Fidder简单使用方法(HTTPS抓取和url替换)
    关于一下个阶段的计划
    JAVA的随机的字符串的封装(基本上够用了)
    Shell Script中的间接变量引用
    进程概念
    int main(int argc, char *argv[])的解读
    存储数组数据到SharedPreferences
    C语言中的基本声明
    C中关于指针数组的用法
  • 原文地址:https://www.cnblogs.com/Hugh-Locke/p/10282447.html
Copyright © 2020-2023  润新知