[POI2000]病毒(AC自动机)

[POI2000]病毒(luogu)

Solution

将所有病毒放到trie树上,将父亲-儿子、自己-fail看作有向边

则题目要求求这个图上是否有一个环,使环上的点不是任何一个病毒的终止点(所以要继承fail的标记)

Code

 

#include <cstdio>
#include <cstdlib>
#include <algorithm>
#include <queue>
using namespace std;
const int N=3e4+10;
char s[N];
int end[N],in[N],vis[N],n,trie[N][2],fail[N],tot;
queue <int> q;
void add()
{
    int now=0;
    for(int i=0;s[i];i++)
    {
        int wh=s[i]-'0';
        if(!trie[now][wh]) trie[now][wh]=++tot;
        now=trie[now][wh];
    }
    end[now]=true;
}
void get_fail()
{
    for(int i=0;i<2;i++)
        if(trie[0][i]) q.push(trie[0][i]);
    while(!q.empty())
    {
        int u=q.front();
        q.pop();
        for(int i=0;i<2;i++)
        {
            int v=trie[u][i];
            if(v) q.push(v),fail[v]=trie[fail[u]][i],end[v]|=end[fail[v]];
            else trie[u][i]=trie[fail[u]][i];
        }
    }
}
void dfs(int u)
{
    if(in[u])
    {
        puts("TAK");
        exit(0);
    }
    if(vis[u] || end[u]) return;
    vis[u]=in[u]=1;
    dfs(trie[u][0]),dfs(trie[u][1]);
    in[u]=0;
}
int main()
{
    scanf("%d",&n);
    while(n--) scanf("%s",s),add();
    get_fail(),dfs(0);
    puts("NIE");
    return 0;
}

 

 

猜你喜欢

转载自www.cnblogs.com/hsez-cyx/p/12424632.html