bzoj2938: [Poi2000]病毒

题目链接

bzoj2938: [Poi2000]病毒

题解

简单的来说,就是构造一个只含0和1的字符串,不能与Trie完成匹配。
dfs判一下trie图上是否存在与根节点相连没有串结尾的环
也就是有串结尾的点和fail指针指向串结尾的点,或指向不能走的点(也就是之前那一坨)的点也不能在环中

代码

#include<bits/stdc++.h> 
using namespace std; 
int n; 
const int maxn = 30007; 
char a[30007]; 
int ch[maxn][2],val[maxn]; 
int sz = 0; 
void Insert(char *s) { 
    int len = strlen(s + 1),now = 0 ; 
    for(int i = 1;i <= len;++ i) { 
        int c = s[i] - '0'; 
        if(!ch[now][c]) 
            ch[now][c] = ++ sz; 
        now = ch[now][c]; 
    } 
    val[now] = 1; 
} 
queue<int>q; 
int fail[maxn]; 
void getfail() { 
    for(int i = 0;i <= 1;++ i) if(ch[0][i]) q.push(ch[0][i]);
    while(!q.empty() ) { 
        int now = q.front(); 
        q.pop(); 
        for(int i = 0;i <= 1;++ i) { 
            if(ch[now][i]) {
                fail[ch[now][i]] = ch[fail[now]][i];
                val[ch[now][i]] |= val[ch[fail[now]][i]]; 
                q.push(ch[now][i]); 
            } 
            else ch[now][i]  = ch[fail[now]][i];    
        } 
    } 
} 
bool vis[maxn],ht[maxn]; 
void dfs(int x) { 
    vis[x] = 1; ht[x] = 1; 
    for(int i =0;i <= 1;++ i) { 
        int v = ch[x][i]; 
        if(v) { 
            if(vis[v]) { 
                puts("TAK"); 
                exit(0); 
            } 
            if(!ht[v] && !val[v]) dfs(v); 
        } 
    } 
    vis[x] = 0; 
} 
int main() { 
    scanf("%d",&n); 
    for(int i = 1;i <= n;++ i) { 
        scanf("%s",a + 1); 
        Insert(a); 
    } 
    getfail(); 
    dfs(0); 
    puts("NIE"); 
    return 0; 
} 

posted @ 2018-07-12 21:27  zzzzx  阅读(125)  评论(0编辑  收藏  举报