P2444 病毒

P2444 病毒

明显,这是让我们在trie图上找一个环。

暴力搜索就可以了。

不过我们还需要注意一个坑点

如果我们当前的后缀是一个病毒的结尾,所以我们要在处理失配指针时还要处理他的后缀是病毒片段。

我觉得这也算是一个写Ac自动机一类题的要注意的坑点吧。

#include<iostream>
#include<algorithm>
#include<cstring>
#include<queue>
#include<cstdio>
using namespace std;
int n;
char data[30100];
int t[30100][2],tail;
int end[60200];
int fail[60200];
void ins()
{
	int now=0,len=strlen(data)-1;
	for(int i=0;i<=len;i++)
	{
		int nxt=data[i]-'0';
		if(!t[now][nxt])	t[now][nxt]=++tail;
		now=t[now][nxt];
	}
	end[now]+=1;
	return ;
}
queue<int>q;
void make_fail()
{
	if(t[0][0])	q.push(t[0][0]);
	if(t[0][1])	q.push(t[0][1]);//直接展开得了
	while(!q.empty())
	{
		int now=q.front();
		q.pop();
		if(t[now][0])
		{
			fail[t[now][0]]=t[fail[now]][0],q.push(t[now][0]);
			if(end[t[fail[now]][0]])	end[t[now][0]]+=1;//处理病毒是否是其后缀
		}
		else	t[now][0]=t[fail[now]][0];
		if(t[now][1])
		{
			fail[t[now][1]]=t[fail[now]][1],q.push(t[now][1]);
			if(end[t[fail[now]][1]])	end[t[now][1]]+=1;	
		}
		else	t[now][1]=t[fail[now]][1];
	}
	return ;
}
bool vis[60200];
void dfs(int now)
{
	if(end[fail[now]])	return ;
	if(vis[now])
	{
		printf("TAK");
		exit(0);
	}
	vis[now]=true;
	if(!end[t[now][0]])	dfs(t[now][0]);
	if(!end[t[now][1]])	dfs(t[now][1]);
	vis[now]=false;
	return ;
}
int main()
{
	scanf("%d",&n);
	for(int i=1;i<=n;i++)
	{
		scanf("%s",data);
		ins();
	}
	make_fail();
	dfs(0);
	printf("NIE");
	return 0;
}
原文地址:https://www.cnblogs.com/Lance1ot/p/9221609.html