[POI2000]病毒

Description:

给出n个01串,求是否存在一个无限长度的01串不包含这n个中任意一个串

Solution:

若该串合法,则截取其循环的部分,相当于在所有01串中没有匹配,即不经过任一01串的末尾标记
所以只要在Trie图上找到一个不经过任何病毒串结尾位置的环即可

#include<bits/stdc++.h>
using namespace std;
const int mxn=3e4+5;
int vis[mxn],ar[mxn];
char str[mxn],p[7500],ans[5];
queue<int > q;

namespace Trie {
    int tot,fail[mxn],val[mxn];
    int t[mxn][26];
    void ins(char *s) {
        int len=strlen(s),u=0;
        for(int i=0;i<len;++i) {
            if(!t[u][s[i]-'0']) t[u][s[i]-'0']=++tot;
            u=t[u][s[i]-'0'];
        }
        val[u]=1;
    };
    void build() {
        for(int i=0;i<2;++i) 
            if(t[0][i]) q.push(t[0][i]);
        while(!q.empty()) {
            int u=q.front(); q.pop();
            val[u]|=val[fail[u]];
            for(int i=0;i<2;++i) {
                if(t[u][i]) fail[t[u][i]]=t[fail[u]][i],q.push(t[u][i]);
                else t[u][i]=t[fail[u]][i];
            }
        }	
    };
    void dfs(int u) {
        if(vis[u]) {
            puts("TAK");
            exit(0);
        }
        vis[u]=1;
        for(int i=0;i<2;++i) {
            if(!val[t[u][i]]&&ar[t[u][i]]<2) {
                ar[t[u][i]]++;
                dfs(t[u][i]);
            }
        }
        vis[u]=0;
    };
}
using namespace Trie;

int main()
{
    int n; scanf("%d",&n);
    for(int i=1;i<=n;++i) 
        scanf("%s",p),ins(p);
    build(); dfs(0); puts("NIE");
    return 0;
}
posted @ 2019-02-15 22:34  cloud_9  阅读(104)  评论(0编辑  收藏  举报