【bzoj2938】[Poi2000]病毒

2938: [Poi2000]病毒

Time Limit: 1 Sec  Memory Limit: 128 MB
Submit: 579  Solved: 304
[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自动机,然后判环即可。
 1 #include<iostream>
 2 #include<cstdio>
 3 #include<cstdlib>
 4 #include<cstring>
 5 #include<ctime>
 6 #include<cmath>
 7 #include<algorithm>
 8 using namespace std;
 9 int n,cnt(1),end[30010],size[30010],q[30010],fail[30010],ins[30010],vis[30010],tr[30010][2];
10 char ch[30010];
11 inline int read()
12 {
13     int x=0,f=1;  char ch=getchar();
14     while(!isdigit(ch))  {if(ch=='-')  f=-1;  ch=getchar();}
15     while(isdigit(ch))  {x=x*10+ch-'0';  ch=getchar();}
16     return x*f;
17 }
18 void Insert()
19 {
20     int now=0,l=strlen(ch+1);
21     for(int i=1;i<=l;i++)
22     {
23         if(!tr[now][ch[i]-'0']) tr[now][ch[i]-'0']=++cnt;
24         now=tr[now][ch[i]-'0'];
25     }
26     end[now]=1;
27 }
28 void build()
29 {
30     int head=0,tail=0;
31     for(int i=0;i<=1;i++)  if(tr[0][i])  q[++tail]=tr[0][i];
32     while(++head<=tail)
33     {
34         int x=q[head];
35         for(int i=0;i<=1;i++)
36         {    
37             int y=tr[x][i];
38             if(!y){tr[x][i]=tr[fail[x]][i];continue;}
39             q[++tail]=y;
40             int temp=fail[x];
41             while(!tr[temp][i]) temp=fail[temp];
42             fail[y]=tr[temp][i];  
43             end[y]|=end[tr[temp][i]];
44         }    
45     }
46 }
47 bool dfs(int x)
48 {
49     ins[x]=1;
50     for(int i=0;i<2;i++)
51     {
52         int v=tr[x][i];
53         if(ins[v])return 1;
54         if(vis[v]||end[v])continue;
55         vis[v]=1;
56         if(dfs(v))return 1;
57     }
58     ins[x]=0;
59     return 0;
60 }
61 int main()
62 {
63     //freopen("cin.in","r",stdin);
64     //freopen("cout.out","w",stdout);
65     n=read();
66     for(int i=1;i<=n;i++)  {scanf("%s",ch+1);  Insert();}
67     build();
68     if(dfs(0))  printf("TAK\n");
69     else printf("NIE\n");
70     return 0;
71 }

 

 

 
 
posted @ 2016-10-26 13:50  chty  阅读(253)  评论(0编辑  收藏  举报