【BZOJ2938】[POI2000]病毒

【BZOJ2938】[POI2000]病毒

题面

bzoj 洛谷

题解

现在看到字符串的题目就是$AC$自动机23333。。。(以前是哈希)

这题和普通的$AC$自动机题有些许不同

这题的文本串并未给出来

怎么办呢?

想一下,如果一个字符串匹配不到任何东西的话,会怎么样

是不是会一直在里面打转转?

所以就在$trie$图中找有没有没有环就行了

注意经过病毒串前缀的节点不可访问

代码

#include <iostream> 
#include <cstdio> 
#include <cstdlib> 
#include <cstring> 
#include <cmath> 
#include <algorithm> 
#include <queue> 
using namespace std; 
const int MAX_N = 3e4 + 5; 
int c[MAX_N][2], fail[MAX_N], End[MAX_N], tot; 
void insert(char *s) {
	int o = 0; 
	for (int i = 0, l = strlen(s); i < l; i++) { 
		int son = s[i] - '0'; 
		if (!c[o][son]) c[o][son] = ++tot; 
		o = c[o][son]; 
	} 
	End[o] = 1; 
} 
void build() { 
	static queue<int> que; 
	for (int i = 0; i < 2; i++) if (c[0][i]) que.push(c[0][i]), fail[c[0][i]] = 0; 
	while (!que.empty()) { 
		int o = que.front(); que.pop(); 
		for (int i = 0; i < 2; i++) 
			if (c[o][i]) fail[c[o][i]] = c[fail[o]][i], End[c[o][i]] |= End[fail[c[o][i]]], que.push(c[o][i]);
			else c[o][i] = c[fail[o]][i]; 
	} 
} 
bool ins[MAX_N], vis[MAX_N]; 
void dfs(int x) { 
	if (ins[x]) puts("TAK"), exit(0);
	if (vis[x] || End[x]) return ;
	vis[x] = ins[x] = 1; 
	dfs(c[x][0]);
	dfs(c[x][1]);
	ins[x] = 0; 
}
int N; char s[MAX_N]; 
int main () {
	scanf("%d", &N);
	for (int i = 1; i <= N; i++) scanf("%s", s), insert(s); 
	build(); 
	dfs(0);
	puts("NIE"); 
	return 0; 
} 
原文地址:https://www.cnblogs.com/heyujun/p/10240278.html