[POI2000]病毒

Posted chtholly

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了[POI2000]病毒相关的知识,希望对你有一定的参考价值。

题意

给定一些字符串,问是否存在一个无限长度的字符串,使得它不包含任何一个给定的串

思路

将所有串加入AC自动机,那么我们从根节点选择的一个无线字符串显然不能经过任何一个带有end标记的节点,不然就说明其中包含了这个节点对应的字符串。

于是用fail标记建成trie图,判断trie图上面有没有一个不经过end标记的环即可

Code:

#include<bits/stdc++.h>
#define N 30005
using namespace std;
int n;
int nxt[N][2],fail[N],ndsum;
char c[N];
bool is_end[N],vis[N],st[N];

void ad(char a[])

    int l=strlen(a),now=0;
    for(int i=0;i<l;++i)
    
        int pp=a[i]-'0';
        if(!nxt[now][pp]) nxt[now][pp]=++ndsum;
        now=nxt[now][pp];
    
    is_end[now]=1;

void getfail()
       
    queue<int> q;
    for(int i=0;i<2;++i) if(nxt[0][i]) q.push(nxt[0][i]);
    while(!q.empty())
    
        int u=q.front();q.pop();
        for(int i=0;i<2;++i)
        if(nxt[u][i]) fail[nxt[u][i]]=nxt[fail[u]][i],q.push(nxt[u][i]),is_end[nxt[u][i]]|=is_end[fail[nxt[u][i]]];
        else nxt[u][i]=nxt[fail[u]][i];
    

bool dfs(int u)

    if(st[u]) return true;
    if(vis[u]) return false;
    vis[u]=st[u]=1;
    for(int i=0;i<2;++i)
    
        if(nxt[u][i]&&!is_end[nxt[u][i]]) if(dfs(nxt[u][i])) return true;
    
    st[u]=0;
    return false;

int main()

    scanf("%d",&n);
    for(int i=1;i<=n;++i)
    
        scanf("%s",c);
        ad(c);
    
    getfail();
    memset(vis,0,sizeof(vis));
    if(dfs(0)) printf("TAK\n");
    else printf("NIE\n");
    return 0;

以上是关于[POI2000]病毒的主要内容,如果未能解决你的问题,请参考以下文章

2938: [Poi2000]病毒

[Poi2000]病毒

Poi2000病毒

P2444 [POI2000]病毒

[bzoj 2938] [Poi2000]病毒]

病毒[POI2000](AC自动机+搜索)