zoukankan      html  css  js  c++  java
  • luoguP2444_[POI2000]病毒

    题意

    给定多个01模式串,问是否存在一个无限长的字符串不包含任何一个模式串。

    分析

    • 好像数据有点水,网上一大堆题解连样例都没过???
    • 多模式串,先把AC自动机建出来再说。
    • 反向考虑,若存在一个无限长的字符串不包含任何一个模式串,那就说明这个字符串可以在AC自动机上无限匹配,所以我们在AC自动机上dfs找环即可。

    代码

    #include <bits/stdc++.h>
    using namespace std;
    const int N=2e5+50;
    bool flag;
    struct ACM{
        int tr[N][2],val[N],fail[N],cnt,x[N],vis[N];
        void init(){
            memset(tr,0,sizeof(tr));
            memset(val,0,sizeof(val));
            memset(fail,0,sizeof(fail));
        }
        void insert(char *s){
            int len=strlen(s);
            int now=0;
            for(int i=0;i<len;i++){
                int id=s[i]-'0';
                if(!tr[now][id]){
                    tr[now][id]=++cnt;
                }
                now=tr[now][id];
            }
            val[now]++;
            x[now]++;
        }
        void build(){
            queue<int> q;
            for(int i=0;i<2;i++){
                if(tr[0][i]){
                    q.push(tr[0][i]);
                    fail[tr[0][i]]=0;
                }
            }
            while(!q.empty()){
                int u=q.front();
                q.pop();
                for(int i=0;i<2;i++){
                    if(tr[u][i]){
                        fail[tr[u][i]]=tr[fail[u]][i];
                        x[tr[u][i]]+=x[tr[fail[u]][i]];
                        q.push(tr[u][i]);
                    }else{
                        tr[u][i]=tr[fail[u]][i];
                    }
                }
            }
        }
        void dfs(int u){
            if(flag){
                return;
            }
            vis[u]=0;
            for(int i=0;i<2;i++){
                int v=tr[u][i];
                if(x[v]){
                    continue;
                }
                if(vis[v]==-1){
                    dfs(v);
                }else if(vis[v]==0){
                    flag=true;
                }
            }
            vis[u]=1;
        }
        void solve(){
            memset(vis,-1,sizeof(vis));
            dfs(0);
        }
    }ac;
    int n;
    char s[N];
    int main(){
        freopen("in.txt","r",stdin);
        scanf("%d",&n);
        ac.init();
        for(int i=0;i<n;i++){
            scanf("%s",s);
            ac.insert(s);
        }
        ac.build();
        ac.solve();
        if(flag){
            printf("TAK
    ");
        }else{
            printf("NIE
    ");
        }
        return 0;
    }
    
  • 相关阅读:
    如何判断第一个节区头的RVA
    从可执行文件中删除.reloc节区
    动态规划(dynamic programming)
    Ubuntu18安装SQL server
    Ubuntu16.04突然断网
    [Toddler's Bottle]做题记录
    BUU | pwnable_orw
    BUU| 基础破解
    web.xml
    PKIX
  • 原文地址:https://www.cnblogs.com/zxcoder/p/11392946.html
Copyright © 2011-2022 走看看