bzoj2938: [Poi2000]病毒

建AC自动机,把所有病毒的节点都删掉,dfs判有没有环,有环就找得到。

#include <iostream>
#include <cstdio>
#include <cstring>
#include <cmath>
#include <cstdlib>
#include <algorithm>
#define N 30304

using namespace std;

int size,root;
int next[N][2],fail[N];
bool safe[N];
int newnode(){
	safe[++size]=1;
	next[size][0]=next[size][1]=0;
	return size;
}
void ins(char *s){
	int now=root;
	for (int i=0;s[i];++i){
		if (!next[now][s[i]-48])
			next[now][s[i]-48]=newnode();
		now=next[now][s[i]-48];
	}
	safe[now]=0;
}
int q[N],qh,qt;
void bfs(){
	fail[root]=root;
	qh=qt=0;
	q[++qt]=root;
	while (qh<qt){
		int u=q[++qh];
		for (int i=0;i<2;++i){
			int v=next[u][i];
			if (!v)
				next[u][i]=u!=root?next[fail[u]][i]:root;
			else{
				fail[v]=u!=root?next[fail[u]][i]:root;
				q[++qt]=v;
			}
		}
		safe[u]&=safe[fail[u]];
	}
}

bool vis[N],found;
bool flag[N];
void dfs(int u){
	vis[u]=1;
	for (int i=0;i<2;++i){
		int v=next[u][i];
		if (!safe[v]) continue;
		if (vis[v]) found=1;
		else dfs(v);
		if (found) return;
	}
	vis[u]=0;
	safe[u]=0;
}

char s[N];
int main(){
	int n;scanf("%d",&n);
	size=0;root=newnode();
	memset(s,0,sizeof(s));
	for (int i=1;i<=n;++i){
		scanf("%s",s);
		ins(s);
	}
	bfs();
	memset(vis,0,sizeof(vis));
	found=0;
	dfs(root);
	puts(found?"TAK":"NIE");
	
	return 0;
}

  

posted @ 2016-01-15 22:58  wangyurzee  阅读(144)  评论(0编辑  收藏  举报