[POI2000] 病毒

题目链接

  • 字符串多模匹配算法——AC自动机,原始的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
*/
posted @   D06  阅读(3)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 地球OL攻略 —— 某应届生求职总结
· 周边上新:园子的第一款马克杯温暖上架
· Open-Sora 2.0 重磅开源!
· 提示词工程——AI应用必不可少的技术
· .NET周刊【3月第1期 2025-03-02】
//雪花飘落效果
点击右上角即可分享
微信分享提示