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;
}

猜你喜欢

转载自www.cnblogs.com/Lance1ot/p/9221609.html