码迷,mamicode.com
首页 > 其他好文 > 详细

bzoj 2938: [Poi2000]病毒

时间:2017-12-23 20:18:59      阅读:174      评论:0      收藏:0      [点我收藏+]

标签:pop   script   void   fine   input   scan   i++   amp   包括   

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]病毒

标签:pop   script   void   fine   input   scan   i++   amp   包括   

原文地址:http://www.cnblogs.com/thmyl/p/8094022.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!