不禁令人想起
洛天依吸毒,好像是吸了熊猫烧香
正常的部分
二进制病毒审查委员会最近发现了如下的规律:某些确定的二进制串是病毒的代码。如果某段代码中不存在任何一段病毒代码,那么我们就称这段代码是安全的。现在委员会已经找出了所有的病毒代码段,试问,是否存在一个无限长的安全的二进制代码。
示例:
例如如果{011, 11, 00000}为病毒代码段,那么一个可能的无限长安全代码就是010101…。如果{01, 11, 000000}为病毒代码段,那么就不存在一个无限长的安全代码。
任务:
请写一个程序:
1.在文本文件WIR.IN中读入病毒代码;
2.判断是否存在一个无限长的安全代码,存在输出TAK,否则输出NIE;
Ps.luogu上输TAK有五十五分
其实和AC自动机并没多大关系,然而它就是这类。
让我们脑补一下,如果存在这个无限串,那么在对病毒库进行匹配的时候,我们的指针会在AC机上绕圈:
我们把失配边(就是fail)、Trie的边认作单向边。顺着之前的思路,如果能够从root走出一个环(环上不能有end节点),则存在这样的串。
另外,如果一个模板串中存在一个危险字串,也就是某个位置fail指针指向一个end节点,那么它之后的节点也都是危险节点:
(危险节点已用红色框出
入坑找环的办法:
从根节点开始DFS,不经过危险节点。来到一个新节点时,将新节点入栈并标记,然后接着DFS,直到回到一个在栈中的节点,也就是构成了环。注意,我们不能路过已经到过,但是不在栈中的点,否则环的相接处会出现“病毒”
然后。。。。
上代码:
#include<cstdio>
#include<string>
#include<algorithm>
#include<cstdlib>
#define maxn 33333
using namespace std;
int n,cnt=0,now=0;
short t[maxn][2],q[maxn],f[maxn],v,hed,til;
bool flg[maxn],vis[maxn],in[maxn];
char s[355];
void DFS(