2938: [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
 
这道题容易想到我们只需要找到一个串它复制一遍,也不存在任意一个代码段,问题在于,我们如何确定是否存在这一个串。
我们可以建立一个后缀自动机,然后把不是结尾的节点通过失配边构成一个图,如果这个图上存在一个环,那么就说明存在一个串,它无论怎样复制也无法构成任意一个代码段。。
 1 #include<iostream>
 2 #include<cstdlib>
 3 #include<cmath>
 4 #include<cstring>
 5 #include<cstdio>
 6 #include<algorithm>
 7 #include<string>
 8 #include<map>
 9 #include<queue>
10 #include<vector>
11 #include<set>
12 #define inf 1000000000
13 #define maxn 100000+5
14 #define maxm 10000+5
15 #define eps 1e-10
16 #define ll long long
17 #define for0(i,n) for(int i=0;i<=(n);i++)
18 #define for1(i,n) for(int i=1;i<=(n);i++)
19 #define for2(i,x,y) for(int i=(x);i<=(y);i++)
20 #define for3(i,x,y) for(int i=(x);i>=(y);i--)
21 #define for4(i,x) for(int i=head[x],y=e[i].go;i;i=e[i].next,y=e[i].go)
22 using namespace std;
23 int read(){
24     int x=0,f=1;char ch=getchar();
25     while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
26     while(ch>='0'&&ch<='9'){x=10*x+ch-'0';ch=getchar();}
27     return x*f;
28 }
29 int n,tot=1,cnt,t[maxn][2],danger[maxn],point[maxn];
30 int in[maxn],head[maxn],num;
31 queue<int> q;
32 char ch[maxm];
33 struct edge{
34     int go,next;
35 }e[maxn];
36 void ins(int u,int v){
37     e[++cnt].go=v;e[cnt].next=head[u];head[u]=cnt;
38 }
39 void insert(){
40     int len=strlen(ch),now=1;
41     for0(i,len-1){
42         if(!t[now][ch[i]-'0'])t[now][ch[i]-'0']=++tot;
43         now=t[now][ch[i]-'0'];
44     }
45     danger[now]=1;
46 }
47 void build(){
48     q.push(1);
49     while(!q.empty()){
50         int x=q.front();q.pop();danger[x]|=danger[point[x]];
51         for0(i,1){
52             int tmp=point[x];
53             while(tmp&&!t[tmp][i])tmp=point[tmp];
54             if(t[x][i]){
55                 point[t[x][i]]=tmp?t[tmp][i]:1;
56                 q.push(t[x][i]); 
57             }else t[x][i]=tmp?t[tmp][i]:1;
58         }
59     }
60 }
61 bool topsort(){
62     int num=0;
63     for1(i,tot)
64         for0(j,1)
65             if(!danger[i]&&!danger[t[i][j]])
66                 ins(i,t[i][j]),in[t[i][j]]++;
67     for1(i,tot)
68         if(!in[i])
69             q.push(i);
70     while(!q.empty()){
71         int x=q.front();q.pop();num++;
72         for4(i,x){
73             in[y]--;
74             if(!in[y])q.push(y);
75         }
76     } 
77     return num==tot;
78 }
79 int main(){
80     //freopen("input.txt","r",stdin);
81     //freopen("output.txt","w",stdout);
82     n=read();
83     for1(i,n){
84         scanf("%s",ch);
85         insert();
86     }
87     build();
88     printf("%s\n",topsort()?"NIE":"TAK");
89     return 0;
90 }
View Code

 

posted @ 2016-06-16 16:16  HTWX  阅读(178)  评论(0编辑  收藏  举报