zoukankan      html  css  js  c++  java
  • BZOJ2938: [Poi2000]病毒

    BZOJ2938: [Poi2000]病毒

    Description

    二进制病毒审查委员会最近发现了如下的规律:某些确定的二进制串是病毒的代码。
    如果某段代码中不存在任何一段病毒代码,那么我们就称这段代码是安全的。
    现在委员会已经找出了所有的病毒代码段,试问,是否存在一个无限长的安全的二进制代码。
    示例:
    例如如果{011, 11, 00000}为病毒代码段,那么一个可能的无限长安全代码就是010101…。
    如果{01, 11, 000000}为病毒代码段,那么就不存在一个无限长的安全代码。
    任务:
    请写一个程序:
    l         读入病毒代码;
    l         判断是否存在一个无限长的安全代码;
    l         将结果输出

    Input

    第一行包括一个整数n,表示病毒代码段的数目。
    以下的n行每一行都包括一个非空的01字符串——就是一个病毒代码段。
    所有病毒代码段的总长度不超过30000。

    Output

    你应在在文本文件WIN.OUT的第一行输出一个单词:
    l         TAK——假如存在这样的代码;
    l         NIE——如果不存在。

    Sample Input

    3
    01
    11
    00000

    Sample Output

    NIE

    题解Here!
    $AC$自动机的裸题了。
    这题只要建出$AC$自动机,然后在这个图上找到任意一个不包含危险节点且经过根节点的环,就说明有解。
    否则无解。
    然后在$AC$自动机的失配指针构建过程中,如果某个节点的失配指针指向的节点是危险的,那么这个节点也一定是危险的。
    这点坑。。。
    然后。。。找环怎么找?
    直接在自动机上大力$DFS$即可。
    然后就是板子了。
    附代码:
    #include<iostream>
    #include<algorithm>
    #include<cstdio>
    #include<queue>
    #include<cstring>
    #define MAXN 30010
    using namespace std;
    int n,size=0;
    bool flag=false,vis[MAXN],used[MAXN];
    char ch[MAXN];
    struct AC{//Aho_Corasick_Automaton
        int fail,val,son[2];
        AC(){
            fail=val=0;
            memset(son,0,sizeof(son));
        }
    }a[MAXN];
    inline int read(){
        int date=0,w=1;char c=0;
        while(c<'0'||c>'9'){if(c=='-')w=-1;c=getchar();}
        while(c>='0'&&c<='9'){date=date*10+c-'0';c=getchar();}
        return date*w;
    }
    inline int idx(char x){return x-'0';}
    void insert(char *s){
    	int u=0,l=strlen(s);
    	for(int i=0;i<l;i++){
    		int c=idx(s[i]);
    		if(!a[u].son[c])a[u].son[c]=++size;
    		u=a[u].son[c];
    	}
        a[u].val=1;
    }
    void buildtree(){
        int u,v;
        queue<int> q;
        for(int i=0;i<=1;i++)
    	if(a[0].son[i]){
    		a[a[0].son[i]].fail=0;
    		q.push(a[0].son[i]);
    	}
        while(!q.empty()){
            u=q.front();
            q.pop();
            for(int i=0;i<=1;i++){
    			if(a[u].son[i]){
    				a[a[u].son[i]].fail=a[a[u].fail].son[i];
    				if(a[a[a[u].son[i]].fail].val)a[a[u].son[i]].val=1;//对,就是这里!
    				q.push(a[u].son[i]);
    			}
    			else
    			a[u].son[i]=a[a[u].fail].son[i];
            }
        }
    }
    void dfs(int x){
        if(flag)return;
        vis[x]=true;
        for(int i=0;i<=1;i++){
            int v=a[x].son[i];
            if(vis[v]){
                flag=true;
                return;
            }
            else if(!a[v].val&&!used[v]){
                used[v]=true;
                dfs(v);
                if(flag)return;
            }
        }
        vis[x]=false;
    }
    void work(){
        dfs(0);
        if(flag)printf("TAK
    ");
        else printf("NIE
    ");
    }
    void init(){
        n=read();
        for(int i=1;i<=n;i++){
            scanf("%s",ch);
            insert(ch);
        }
        buildtree();
    }
    int main(){
        init();
        work();
        return 0;
    }
    
  • 相关阅读:
    HDU 4278 Faulty Odometer 8进制转10进制
    hdu 4740 The Donkey of Gui Zhou bfs
    hdu 4739 Zhuge Liang's Mines 随机化
    hdu 4738 Caocao's Bridges tarjan
    Codeforces Gym 100187M M. Heaviside Function two pointer
    codeforces Gym 100187L L. Ministry of Truth 水题
    Codeforces Gym 100187K K. Perpetuum Mobile 构造
    codeforces Gym 100187J J. Deck Shuffling dfs
    codeforces Gym 100187H H. Mysterious Photos 水题
    windows服务名称不是单个单词的如何启动?
  • 原文地址:https://www.cnblogs.com/Yangrui-Blog/p/9427284.html
Copyright © 2011-2022 走看看