bzoj 2938: [Poi2000]病毒

Posted Soda

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了bzoj 2938: [Poi2000]病毒相关的知识,希望对你有一定的参考价值。

2938: [Poi2000]病毒

Time Limit: 1 Sec  Memory Limit: 128 MB
Submit: 1111  Solved: 556
[Submit][Status][Discuss]

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
/*
    建立AC自动机,在不能走每个单词最后一个字母的前提下,如果某个字符串在自动机上无法匹配,
    则说明可以找到无限长的字符串。
    为了方便起见,将所有的fail指针合并,最后在自动机上搜索就行了。 
*/
#include<iostream>
#include<cstdio>
#include<cstring>
#include<queue>
using namespace std;
#define maxn 30010
int n,sz=1,a[maxn][2],fail[maxn],word[maxn];
bool ins[maxn],vis[maxn];
char s[maxn];
void insert(){
    int now=1,len=strlen(s);
    for(int i=0;i<len;i++){
        int t=s[i]-0;
        if(!a[now][t])a[now][t]=++sz;
        now=a[now][t];
    }
    word[now]=1;
}
void acmach(){
    queue<int>q;
    q.push(1);fail[1]=0;
    while(!q.empty()){
        int now=q.front();q.pop();
        for(int i=0;i<2;i++){
            if(!a[now][i]){a[now][i]=a[fail[now]][i];continue;}
            int k=fail[now];
            while(!a[k][i])k=fail[k];
            fail[a[now][i]]=a[k][i];
            word[a[now][i]]|=word[a[k][i]];
            q.push(a[now][i]);
        }
    }
}
bool dfs(int x){
    ins[x]=1;
    for(int i=0;i<2;i++){
        if(ins[a[x][i]])return 1;
        if(vis[a[x][i]]||word[a[x][i]])continue;
        vis[a[x][i]]=1;
        if(dfs(a[x][i]))return 1;
    }
    ins[x]=0;
    return 0;
}
int main(){
    for(int i=0;i<2;i++)a[0][i]=1;
    scanf("%d",&n);
    for(int i=1;i<=n;i++){
        scanf("%s",s);
        insert();
    }
    acmach();
    if(dfs(1))printf("TAK");
    else printf("NIE");
    return 0;
}

 

以上是关于bzoj 2938: [Poi2000]病毒的主要内容,如果未能解决你的问题,请参考以下文章

BZOJ2938 [Poi2000]病毒 AC自动机

BZOJ2938: [Poi2000]病毒

[bzoj 2938] [Poi2000]病毒]

bzoj2938poi2000病毒

2938: [Poi2000]病毒

2938. [POI2000]病毒AC自动机