1. 程式人生 > >【BZOJ2938】[POI2000]病毒

【BZOJ2938】[POI2000]病毒

節點 ostream max puts www. push stream bool space

【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; 
} 

【BZOJ2938】[POI2000]病毒