洛谷2444 [POI2000]病毒(AC自动机)(DFS)

题目

二进制病毒审查委员会最近发现了如下的规律:某些确定的二进制串是病毒的代码。如果某段代码中不存在任何一段病毒代码,那么我们就称这段代码是安全的。现在委员会已经找出了所有的病毒代码段,试问,是否存在一个无限长的安全的二进制代码。

示例:
例如如果{011, 11, 00000}为病毒代码段,那么一个可能的无限长安全代码就是010101…。如果{01, 11, 000000}为病毒代码段,那么就不存在一个无限长的安全代码。

任务:
请写一个程序:
1.在文本文件WIR.IN中读入病毒代码;
2.判断是否存在一个无限长的安全代码;
3.将结果输出到文件WIR.OUT中。

题解

AC自动机+DFS判环
给病毒代码建字典树,并建立fail指针。
要求一个无限长的安全代码实际上就是要在AC自动机上找到一个不包含结尾标记的环,当然,如果一个fail指针指向的节点有结尾标记,那么这个点也不能选,因为到了这个节点相当于到了那个节点,也就是说它的后缀是病毒代码。
为了方便操作,我们可以把没有孩子的尾节点直接接上fail。
接下来就是一个dfs判断是否有环,注意不能走有标记的节点。

代码

#include
#include
#include
using namespace std;
const int maxn=2010,maxl=30010;
int n;
char s[maxl];

struct tree{int fail,son[2];bool c;}tr[maxl];int tot=1,root=1;

void insert()
{
    int x=root;
    int len=strlen(s+1);
    for(int i=1;i<=len;i++)
    {
        int k=s[i]-'0';
        if(!tr[x].son[k]) tr[x].son[k]=++tot;
        x=tr[x].son[k];
    }
    tr[x].c=true;
}

int head,tail,q[maxl];
void makefail()
{
    head=0,tail=1;q[0]=root;
    while(head

 

你可能感兴趣的:(刷题之路,递归/DFS,AC自动机)