[POI2000] 病毒

  • 字符串多模匹配算法——AC自动机
  • 构建不含“叶节点”的Trie图
  • 如果一个节点在环上,那么以它为起点搜索一定能找到这个环
  • 调试程序:栈的输出是倒序的
点击查看代码
#include <bits/stdc++.h>
using namespace std;
int t[30005][2],tot,fail[30005];
bool e[30005],v[30005],f[30005];
void insert(string s)
{
	int p=0;
	for(int i=0;i<s.size();i++)
	{
		if(t[p][s[i]-'0']==0)
		{
			tot++;
			t[p][s[i]-'0']=tot;
		}
		p=t[p][s[i]-'0'];
	}
	e[p]=true;
}
queue<int>q;
void build()
{
	for(int i=0;i<2;i++)
	{
		if(t[0][i]!=0)
		{
			q.push(t[0][i]);
		}
	}
	while(!q.empty())
	{
		int n1=q.front();
		q.pop();
		for(int i=0;i<2;i++)
		{
			if(t[n1][i]!=0)
			{
				fail[t[n1][i]]=t[fail[n1]][i];
				e[t[n1][i]]=e[t[n1][i]]|e[fail[t[n1][i]]];
				/*
				原始的end数组,只能预防从首字母开始的病毒串 
				要预防所有的病毒串,就必须:让end数组遍布字典树的一切后缀
				fail数组恰好能实现这样的传递 
				*/
				q.push(t[n1][i]);
			}
			else
			{
				t[n1][i]=t[fail[n1]][i];
			}
		}
	}
}
void dfs(int n1)
{
	v[n1]=true;
	for(int i=0;i<2;i++)
	{
		if(e[t[n1][i]]==false&&f[t[n1][i]]==false)
		{
			if(v[t[n1][i]]==true)
			{
				puts("TAK");
				exit(0); 
			}
			dfs(t[n1][i]);
			f[t[n1][i]]=true;
		}
	}
	v[n1]=false;
}
int main()
{
//	freopen("P2444_1.in","r",stdin);
	int n;
	cin>>n;
	string s;
	for(int i=1;i<=n;i++)
	{
		cin>>s;
		insert(s);
	}
	build();
	dfs(0);
	puts("NIE");
	return 0;
}
/*
11
1100
1110
0111
00100
1010
00101111
00000
1000
01101
01010101
11111
*/
![](https://img2024.cnblogs.com/blog/2453301/202401/2453301-20240124162302238-530463825.jpg)
posted @ 2024-01-24 16:19  D06  阅读(3)  评论(0编辑  收藏  举报