【题解】【POI2000】病毒

题目链接

这题让我们构造一个无限长的,不包括给定字符串的01串。

把给定字符串放到(AC)自动机上,在结尾处打上标记。

发现,如果我们要构造一个无限长的串,必然要有一个环。

那么这个环上就一定不能有结尾标记。

考虑哪些情况下有结尾标记:

一个是当当前点是单词结尾的时候。

另一个,是当当前节点的失配指针(fail)指向的后缀是结尾的时候。

那么做完这些,剩下的任务就是在(dfs)上找一个环了。

(Code:)

#include<cstdio>
#include<iostream>
#include<cstring>
#include<queue>
#include<string>
#include<cstdlib>
using namespace std;
const int N=40010;
char s[40000];
int vis[N],p[N],n;
int tot,in[N],tr[N][2];
int fail[N];
queue<int>q;
void dfs(int x){
	if(in[x]){
		printf("TAK
");
		exit(0);
	}
	if(vis[x]||p[x])return;
	in[x]=vis[x]=1;
	dfs(tr[x][0]);
	dfs(tr[x][1]);
	in[x]=0;
}
int main(){
	scanf("%d",&n);
	for(int i=1;i<=n;++i){
		scanf("%s",s+1);
		int POS;
		for(int j=1,u=0;s[j];++j){
			int x=s[j]-'0';
			if(!tr[u][x])tr[u][x]=++tot;
			u=tr[u][x],POS=u;
		}
		p[POS]=1;
	}
	for(int i=0;i<=1;++i)if(tr[0][i])q.push(tr[0][i]);
	while(!q.empty()){
		int u=q.front();q.pop();
		for(int i=0;i<=1;++i){
			if(tr[u][i])fail[tr[u][i]]=tr[fail[u]][i],q.push(tr[u][i]),p[tr[u][i]]|=p[fail[tr[u][i]]];
			else tr[u][i]=tr[fail[u]][i];
		}
	}
	dfs(0);
	printf("NIE
");
	return 0;
}
原文地址:https://www.cnblogs.com/h-lka/p/12201254.html