BZOJ2938: [Poi2000]病毒

传送门

AC自动机上的各种处理一直让我很迷。一个主要懵逼的点是不清楚对于不存在的字母所对应的方案如何处理。做了两道题大概比较清楚了。

其实对于不存在的字母节点不需要特殊的处理。因为如果累加方案的话,其方案会自动累加到$root$节点。而其fail指针也会自动指向自己。

另外这道题的判环参考了黄学长的代码,类似于一个简化版的tarjan。

//BZOJ 2938
//by Cydiater
//2016.10.18
#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <cmath>
#include <string>
#include <cstring>
#include <iomanip>
#include <queue>
#include <map>
#include <ctime>
#include <algorithm>
using namespace std;
#define ll long long
#define up(i,j,n)		for(int i=j;i<=n;i++)
#define down(i,j,n)		for(int i=j;i>=n;i--)
const int MAXN=1e6+5;
const int oo=0x3f3f3f3f;
inline int read(){
	char ch=getchar();int x=0,f=1;
	while(ch>‘9‘||ch<‘0‘){if(ch==‘-‘)f=-1;ch=getchar();}
	while(ch>=‘0‘&&ch<=‘9‘){x=x*10+ch-‘0‘;ch=getchar();}
	return x*f;
}
int N,len,next[MAXN][2],fail[MAXN],cnt=0,head,tail,q[MAXN];
bool end[MAXN],vis[MAXN],ins[MAXN];
char s[MAXN];
namespace solution{
	void insert(){
		int now=0;
		up(i,1,len){
			int num=s[i]-‘0‘;
			if(!next[now][num])next[now][num]=++cnt;
			now=next[now][num];
		}
		end[now]=1;
	}
	void init(){
		N=read();
		memset(end,0,sizeof(end));
		up(i,1,N){
			scanf("%s",s+1);
			len=strlen(s+1);
			insert();
		}
	}
	void buildAC(){
		head=1;tail=0;
		up(i,0,1)if(next[0][i])q[++tail]=next[0][i];
		for(;head<=tail;head++){
			int now=q[head];end[now]|=end[fail[now]];
			up(i,0,1){
				int son=next[now][i];
				if(son>0){
					fail[son]=next[fail[now]][i];
					q[++tail]=son;
				}
				else next[now][i]=next[fail[now]][i];
			}
		}
	}
	bool dfs(int node){
		ins[node]=1;
		up(i,0,1){
			int son=next[node][i];
			if(ins[son])return 1;
			if(vis[son]||end[son])continue;
			vis[son]=1;
			if(dfs(son))return 1;
		}
		ins[node]=0;
		return 0;
	}
	void slove(){
		buildAC();
		memset(vis,0,sizeof(vis));
		if(dfs(0))puts("TAK");
		else      puts("NIE");
	}
}
int main(){
	using namespace solution;
	init();
	slove();
	return 0;
}
时间: 2024-08-03 21:30:36

BZOJ2938: [Poi2000]病毒的相关文章

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

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

[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}为病毒代码段,那么一

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}为病毒代码段,那么就

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