【bzoj2938】[Poi2000]病毒
2938: [Poi2000]病毒
Time Limit: 1 Sec Memory Limit: 128 MBSubmit: 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
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 }