P2444 [POI2000]病毒

题目描述

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

示例:

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

任务:

请写一个程序:

1.在文本文件WIR.IN中读入病毒代码;

?2.判断是否存在一个无限长的安全代码;

?3.将结果输出到文件WIR.OUT中。

输入输出格式

输入格式:

在文本文件WIR.IN的第一行包括一个整数n (n≤2000)(n\le 2000)(n≤2000) ,表示病毒代码段的数目。以下的n行每一行都包括一个非空的01字符串——就是一个病毒代码段。所有病毒代码段的总长度不超过30000。

输出格式:

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

TAK——假如存在这样的代码;

NIE——如果不存在。

输入输出样例

输入样例#1:

3
01
11
00000  

输出样例#1:

NIE

Solution:

  本题AC自动机+dfs。

  直接对n个串构建出AC自动机,在求fail时,顺带把会出现单词作为后缀的节点标记,直接用失配边的end值更新当前节点就好了,然后从根节点跑一遍dfs,每次都不走那些被标记的节点或者已经搜索过肯定无解的节点,那么只要搜到了环,就说明可行。

代码:

 1 #include<bits/stdc++.h>
 2 #define il inline
 3 #define ll long long
 4 #define For(i,a,b) for(int (i)=(a);(i)<=(b);(i)++)
 5 #define Bor(i,a,b) for(int (i)=(b);(i)>=(a);(i)--)
 6 using namespace std;
 7 const int N=30005;
 8 int trie[N][2],cnt,fail[N],n;
 9 bool ed[N],vis[N],ct[N];
10 char s[N];
11
12 il void insert(char *s){
13     int len=strlen(s),p=0,x;
14     For(i,0,len-1){
15         x=s[i]-‘0‘;
16         if(!trie[p][x])trie[p][x]=++cnt;
17         p=trie[p][x];
18     }
19     ed[p]=1;
20 }
21
22 il void bfs(){
23     queue<int>q;
24     For(i,0,1) if(trie[0][i]) q.push(trie[0][i]);
25     while(!q.empty()){
26         int u=q.front();q.pop();
27         For(i,0,1){
28             int &v=trie[u][i];
29             if(v) fail[v]=trie[fail[u]][i],ed[v]|=ed[fail[v]],q.push(v);
30             else v=trie[fail[u]][i];
31         }
32     }
33 }
34
35 il void dfs(int now){
36     if(vis[now]) puts("TAK"),exit(0);
37     if(ct[now]||ed[now])return;
38     vis[now]=ct[now]=1;
39     dfs(trie[now][0]),dfs(trie[now][1]);
40     vis[now]=0;
41 }
42
43 il void init(){
44     scanf("%d",&n);
45     For(i,1,n) scanf("%s",s),insert(s);
46     bfs();
47     dfs(0);
48     puts("NIE");
49 }
50
51 int main(){
52     init();
53     return 0;
54 }

原文地址:https://www.cnblogs.com/five20/p/9473479.html

时间: 2024-08-08 16:26:35

P2444 [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 二进制病毒审查委员会最近发现了如下的规律:某些确定的二进制串是病毒的代码.如果某段代码中不存在任何一段病毒代码,那么我们就称这段代码是安全的.现在委员会已经找出

[Poi2000]病毒

Time Limit: 1 Sec  Memory Limit: 128 MB Submit: 993  Solved: 500 [Submit][Status][Discuss] Description 二进制病毒审查委员会最近发现了如下的规律:某些确定的二进制串是病毒的代码.如果某段代码中不存在任何一段病毒代码,那么我们就称这段代码是安全的.现在委员会已经找出了所有的病毒代码段,试问,是否存在一个无限长的安全的二进制代码. 示例: 例如如果{011, 11, 00000}为病毒代码段,那么一

[日常摸鱼][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

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

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

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

【题解】P2444 病毒

[题解][P2444 POI2000]病毒 一道\(ac\)自动机好题... 考虑危险的字符串是什么意思,就是在这个文本串中有模式串的匹配,这样的匹配可以通过\(ac\)自动机完成. 那么给定一个字符串如何判断是否有病毒,直接就是看ac自动机是否匹配成功. 考虑"无限长的安全字符串"代表什么意思,就是在\(ac\)自动机找到一个环.可以用阉割版的\(tarjin\) #include<bits/stdc++.h> using namespace std; #define R