bzoj2938: [Poi2000]病毒

传送门:http://www.lydsy.com:808/JudgeOnline/problem.php?id=2938

思路:构建AC自动机,无限长的安全代码就是能一直在AC自动机上匹配而匹配不上任何一个危险串。依旧是匹配指针不能走到危险串的结尾点x,fail指针指向x的y也不能走,因为根据fail的定义,x这个危险串是y的后缀。找出危险节点后就是找环了,有环就有无限长的安全代码,否则没有。

#include<cstdio>
#include<cstring>
#include<algorithm>
const int maxn=30010;
using namespace std;
int n;char s[maxn];

struct AC_DFA{
	int tot,ch[maxn][2],fail[maxn],q[maxn],head,tail;bool dang[maxn],bo[maxn],ins[maxn];
	void insert(){
		int p=0;
		for (int i=0;i<(int)strlen(s);p=ch[p][s[i]-'0'],i++) if (!ch[p][s[i]-'0']) ch[p][s[i]-'0']=++tot;
		dang[p]=1;
	}
	void getfail(){
		head=0,q[tail=1]=0,fail[0]=-1;
		while (head!=tail){
			int x=q[++head];
			for (int i=0;i<=1;i++)
				if (ch[x][i])
					q[++tail]=ch[x][i],fail[ch[x][i]]=x==0?0:ch[fail[x]][i],dang[ch[x][i]]|=dang[fail[ch[x][i]]];
				else ch[x][i]=x==0?0:ch[fail[x]][i];
		}
	}
	bool dfs(int x){
		ins[x]=1;
		for (int i=0;i<=1;i++){
			int v=ch[x][i];
			if (ins[v]) return 1;
			if (bo[v]||dang[v]) continue;
			bo[v]=1;
			if (dfs(v)) return 1;
		}
		ins[x]=0;return 0;
	}
}T;

int main(){
	scanf("%d",&n);
	for (int i=1;i<=n;i++) scanf("%s",s),T.insert();
	T.getfail(),puts(T.dfs(0)?"TAK":"NIE");
	return 0;
}


posted @ 2015-07-26 14:58  orzpps  阅读(118)  评论(0编辑  收藏  举报