[Poi2000]病毒

Time Limit: 1 Sec  Memory Limit: 128 MB
Submit: 993  Solved: 500
[Submit][Status][Discuss]

Description

二进制病毒审查委员会最近发现了如下的规律:某些确定的二进制串是病毒的代码。如果某段代码中不存在任何一段病毒代码,那么我们就称这段代码是安全的。现在委员会已经找出了所有的病毒代码段,试问,是否存在一个无限长的安全的二进制代码。

示例:

例如如果{011, 11, 00000}为病毒代码段,那么一个可能的无限长安全代码就是010101…。如果{01, 11,
000000}为病毒代码段,那么就不存在一个无限长的安全代码。

任务:

请写一个程序:

  1. 读入病毒代码;
  2. 判断是否存在一个无限长的安全代码;
  3. 将结果输出

Input

第一行包括一个整数n,表示病毒代码段的数目。以下的n行每一行都包括一个非空的01字符串——就是一个病毒代码段。所有病毒代码段的总长度不超过30000。

Output

你应在在文本文件WIN.OUT的第一行输出一个单词:

  1. TAK——假如存在这样的代码;
  2. NIE——如果不存在。

Sample Input

3
01
11
00000

Sample Output

NIE

思路

AC自动机+拓扑序列;

代码实现

 1 #include<cstdio>
 2 const int maxn=3e4+10;
 3 int n;
 4 char ch[maxn];
 5 int next[maxn][2],fail[maxn],sz=2;
 6 bool end[maxn];
 7 void ins(){
 8     int a;
 9     scanf("%s",ch);
10     for(int i=0,j=0;;i++){
11         if(!ch[i]){end[j]=1;break;}
12         a=ch[i]-‘0‘;
13         if(!next[j][a]) next[j][a]=++sz;
14         j=next[j][a];
15     }
16 }
17 int q[maxn],head,tail;
18 void build(){
19     int a,b;
20     head=0,tail=2;
21     q[0]=1,q[1]=2;
22     while(head<tail){
23         a=q[head++];
24         if(next[a][0]){
25             b=fail[a];
26             while(!next[b][0]) b=fail[b];
27             fail[next[a][0]]=next[b][0];
28             if(end[next[b][0]]) end[next[a][0]]=1;
29             q[tail++]=next[a][0];
30         }
31         else next[a][0]=next[fail[a]][0];
32         if(next[a][1]){
33             b=fail[a];
34             while(!next[b][1]) b=fail[b];
35             fail[next[a][1]]=next[b][1];
36             if(end[next[b][1]]) end[next[a][1]]=1;
37             q[tail++]=next[a][1];
38         }
39         else next[a][1]=next[fail[a]][1];
40     }
41 }
42 int tot;
43 int point[maxn],nxt[maxn<<1],v[maxn<<1],in[maxn];
44 bool vis[maxn];
45 void add(int x,int y){tot++,nxt[tot]=point[x],point[x]=tot,v[tot]=y;}
46 void dfs(int k){
47     vis[k]=1;
48     add(k,next[k][0]);in[next[k][0]]++;
49     if(!vis[next[k][0]]&&!end[next[k][0]]) dfs(next[k][0]);
50     add(k,next[k][1]);in[next[k][1]]++;
51     if(!vis[next[k][1]]&&!end[next[k][1]]) dfs(next[k][1]);
52 }
53 bool f_ring(){
54     int cnt=0,a;
55     head=tail=0;
56     for(int i=0;i<sz;i++) if(!in[i]) q[tail++]=i;
57     while(head<tail){
58         a=q[head++],cnt++;
59         for(int i=point[a];i;i=nxt[i]){
60             in[v[i]]--;
61             if(!in[v[i]]) q[tail++]=v[i];
62         }
63     }
64     return cnt<sz;
65 }
66 int main(){
67     scanf("%d",&n);
68     next[0][0]=1,next[0][1]=2;
69     for(int i=1;i<=n;i++) ins();
70     build();
71     dfs(0);
72     if(f_ring()) puts("TAK");
73     else puts("NIE");
74     return 0;
75 }
时间: 2024-11-04 05:04:14

[Poi2000]病毒的相关文章

[bzoj 2938] [Poi2000]病毒]

传送门:http://www.lydsy.com/JudgeOnline/problem.php?id=2938 [Poi2000]病毒 Time Limit: 1 Sec  Memory Limit: 128 MBSubmit: 870  Solved: 447[Submit][Status][Discuss] Description 二进制病毒审查委员会最近发现了如下的规律:某些确定的二进制串是病毒的代码.如果某段代码中不存在任何一段病毒代码,那么我们就称这段代码是安全的.现在委员会已经找出

BZOJ2938 [Poi2000]病毒 【AC自动机】

题目 二进制病毒审查委员会最近发现了如下的规律:某些确定的二进制串是病毒的代码.如果某段代码中不存在任何一段病毒代码,那么我们就称这段代码是安全的.现在委员会已经找出了所有的病毒代码段,试问,是否存在一个无限长的安全的二进制代码. 示例: 例如如果{011, 11, 00000}为病毒代码段,那么一个可能的无限长安全代码就是010101-.如果{01, 11, 000000}为病毒代码段,那么就不存在一个无限长的安全代码. 任务: 请写一个程序: l 读入病毒代码: l 判断是否存在一个无限长的

P2444 [POI2000]病毒

题目描述 二进制病毒审查委员会最近发现了如下的规律:某些确定的二进制串是病毒的代码.如果某段代码中不存在任何一段病毒代码,那么我们就称这段代码是安全的.现在委员会已经找出了所有的病毒代码段,试问,是否存在一个无限长的安全的二进制代码. 示例: 例如如果{011, 11, 00000}为病毒代码段,那么一个可能的无限长安全代码就是010101….如果{01, 11, 000000}为病毒代码段,那么就不存在一个无限长的安全代码. 任务: 请写一个程序: 1.在文本文件WIR.IN中读入病毒代码:

2938: [Poi2000]病毒

Description 二进制病毒审查委员会最近发现了如下的规律:某些确定的二进制串是病毒的代码.如果某段代码中不存在任何一段病毒代码,那么我们就称这段代码是安全的.现在委员会已经找出了所有的病毒代码段,试问,是否存在一个无限长的安全的二进制代码. 示例: 例如如果{011, 11, 00000}为病毒代码段,那么一个可能的无限长安全代码就是010101-.如果{01, 11, 000000}为病毒代码段,那么就不存在一个无限长的安全代码. 任务: 请写一个程序: l 读入病毒代码: l 判断是

Poi2000病毒

zz://https://www.cnblogs.com/Miracevin/p/9710746.html 二进制病毒审查委员会最近发现了如下的规律:某些确定的二进制串是病毒的代码.如果某段代码中不存在任何一段病毒代码,那么我们就称这段代码是安全的.现在委员会已经找出了所有的病毒代码段,试问,是否存在一个无限长的安全的二进制代码. 示例: 例如如果{011, 11, 00000}为病毒代码段,那么一个可能的无限长安全代码就是010101….如果{01, 11, 000000}为病毒代码段,那么就

BZOJ2938: [Poi2000]病毒

传送门 AC自动机上的各种处理一直让我很迷.一个主要懵逼的点是不清楚对于不存在的字母所对应的方案如何处理.做了两道题大概比较清楚了. 其实对于不存在的字母节点不需要特殊的处理.因为如果累加方案的话,其方案会自动累加到$root$节点.而其fail指针也会自动指向自己. 另外这道题的判环参考了黄学长的代码,类似于一个简化版的tarjan. //BZOJ 2938 //by Cydiater //2016.10.18 #include <iostream> #include <cstdio&

BZOJ 2938 Poi2000 病毒 AC自动机+拓扑排序

题目大意:给定n个01串,问是否存在一个无限长的01串,不包含这n个01串中的任何一个 建出Trie图之后判环即可 我这傻逼一开始居然跑了一个DFS去判环23333 #include <cstdio> #include <cstring> #include <iostream> #include <algorithm> #define M 30300 using namespace std; int n; char s[M]; namespace Aho_C

[日常摸鱼][POI2000]病毒-Tire图(AC自动机)+dfs

https://www.luogu.org/problemnew/show/P2444 (没有bzoj权限号T_T) 字符串题对我这种傻逼来说真是太难了x 题意:输入$n$个01组成的模式串串,判断是否存在一个无限长的01串满足任何给定的模式串都不是这个串的子串,$n \leq 2000,\sum len(str) \leq 30000$ 首先用模式串构造出AC自动机(其实应该叫Trie图),题目要求的串如果存在,那就相当于在Trie图上存在一个环,这个环不包含任何一个模式串,所以只要构造出来T

【BZOJ】【2938】【POI2000】病毒

AC自动机 好题>_<(其实是一次AC有些感动) 嗯要找到无限长的一个字符串不包含任何一个模板串,就意味着在AC自动机(Trie图)上找到一个不经过任何一个危险结点的环,深搜一下就好了……记得离开某个结点的时候要清除标记!有点像tarjan…… 1 /************************************************************** 2 Problem: 2938 3 User: Tunix 4 Language: C++ 5 Result: Acce