2938: [Poi2000]病毒
Time Limit: 1 Sec Memory Limit: 128 MBSubmit: 69 Solved: 35
[Submit][Status]
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
01
11
00000
Sample Output
NIE
题解:
首先我们构造出AC自动机,然后把出边补齐,也就是trie图。
然后所有的节点以trie为边构成了一张有向图,我们需要在非危险节点上找有没有环,topsort即可。
代码:
1 #include<cstdio> 2 3 #include<cstdlib> 4 5 #include<cmath> 6 7 #include<cstring> 8 9 #include<algorithm> 10 11 #include<iostream> 12 13 #include<vector> 14 15 #include<map> 16 17 #include<set> 18 19 #include<queue> 20 21 #include<string> 22 23 #define inf 1000000000 24 25 #define maxn 100000+5 26 27 #define maxm 20000000+5 28 29 #define eps 1e-10 30 31 #define ll long long 32 33 #define pa pair<int,int> 34 35 #define for0(i,n) for(int i=0;i<=(n);i++) 36 37 #define for1(i,n) for(int i=1;i<=(n);i++) 38 39 #define for2(i,x,y) for(int i=(x);i<=(y);i++) 40 41 #define for3(i,x,y) for(int i=(x);i>=(y);i--) 42 43 #define mod 1000000007 44 45 using namespace std; 46 47 inline int read() 48 49 { 50 51 int x=0,f=1;char ch=getchar(); 52 53 while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();} 54 55 while(ch>='0'&&ch<='9'){x=10*x+ch-'0';ch=getchar();} 56 57 return x*f; 58 59 } 60 int n,m,tot,cnt,inp[maxn],head[maxn],t[maxn][2],go[maxn]; 61 struct edge{int go,next;}e[maxn]; 62 bool v[maxn]; 63 queue<int>q; 64 char s[maxn]; 65 inline void insert(int x,int y) 66 { 67 e[++tot]=(edge){y,head[x]};head[x]=tot; 68 } 69 inline void add() 70 { 71 scanf("%s",s+1);m=strlen(s+1);int now=1; 72 for1(i,m) 73 { 74 int x=s[i]-'0'; 75 if(!t[now][x])t[now][x]=++cnt; 76 now=t[now][x]; 77 } 78 v[now]=1; 79 } 80 void bfs() 81 { 82 q.push(1); 83 while(!q.empty()) 84 { 85 int x=q.front(),y,j;q.pop();v[x]|=v[go[x]]; 86 for0(i,1) 87 { 88 j=go[x]; 89 while(j&&!t[j][i])j=go[j]; 90 if(t[x][i]) 91 { 92 go[y=t[x][i]]=j?t[j][i]:1; 93 q.push(y); 94 }else t[x][i]=j?t[j][i]:1; 95 } 96 } 97 } 98 bool topsort() 99 { 100 int num=0; 101 for1(i,cnt)for0(j,1)if(!v[i]&&!v[t[i][j]])insert(i,t[i][j]),inp[t[i][j]]++; 102 for1(i,cnt)if(!inp[i])q.push(i); 103 while(!q.empty()) 104 { 105 int x=q.front();q.pop();num++; 106 for(int i=head[x],y;i;i=e[i].next) 107 { 108 inp[y=e[i].go]--; 109 if(!inp[y])q.push(y); 110 } 111 } 112 return num==cnt; 113 } 114 115 int main() 116 117 { 118 119 freopen("input.txt","r",stdin); 120 121 freopen("output.txt","w",stdout); 122 123 n=read();cnt=1; 124 for1(i,n)add(); 125 bfs(); 126 printf("%s ",topsort()?"NIE":"TAK"); 127 128 return 0; 129 130 }