[POI2000]病毒 [洛谷]P2444

来源:互联网 发布:w7 mysql更改密码 编辑:程序博客网 时间:2024/06/07 19:26
  • 题目描述
    二进制病毒审查委员会最近发现了如下的规律:某些确定的二进制串是病毒的代码。如果某段代码中不存在任何一段病毒代码,那么我们就称这段代码是安全的。现在委员会已经找出了所有的病毒代码段,试问,是否存在一个无限长的安全的二进制代码。
  • 输入输出格式

    • 输入格式:
      在文本文件WIR.IN的第一行包括一个整数n(n\le 2000)(n≤2000),表示病毒代码段的数目。以下的n行每一行都包括一个非空的01字符串——就是一个病毒代码段。所有病毒代码段的总长度不超过30000。
    • 输出格式:
      在文本文件WIR.OUT的第一行输出一个单词:
      TAK——假如存在这样的代码;
      NIE——如果不存在。
  • 思路
    这种多串匹配的问题,直接就想到AC自动机。
    不过这道题要变一下,转化为AC自动机上沿着trie上的边和fail指针走是否存在环。
    然后就判环。

#include <bits/stdc++.h>using namespace std ;const int maxn = 3e5+5 ;int n, m, h, s[maxn][2], tim[maxn], fail[maxn], fa[maxn], tot, p, q, ch[maxn] ;char pat[maxn] ;void insert() {    int len = strlen(pat+1) ;    int i, j, k ;    p = h ;    for ( i = 1 ; i <= len ; i ++ ) {        k = pat[i] - '0' ;        if ( s[p][k] ) {            p = s[p][k] ;           } else {            ( s[p][k] = ++tot )[fa] = p ;            p = s[p][k] ;            ch[p] = pat[i] ;        }    }    ++tim[p] ;}queue <int> Q ;void calc() {    int i, j, k, l, r, x ;    Q.push(h) ;    while ( !Q.empty() ) {        x = Q.front() ;        Q.pop() ;        for ( i = 0 ; i < 2 ; i ++ )            if ( s[x][i] ) {                for ( p = x[fail] ; p && !s[p][i] ; p = p[fail] ) ;                s[x][i][fail] = p? s[p][i]:h ;                if ( s[x][i][fail][tim] ) s[x][i][tim] = 1 ;                Q.push(s[x][i]) ;            } else s[x][i] = s[x[fail]][i] ;    }}bool vis[maxn], inq[maxn] ;void check ( int x ) {    printf ( "%d ch=%c fa=%d fail=%d tim=%d\n", x, ch[x], fa[x], fail[x], tim[x] ) ;    for ( int i = 0 ; i < 2 ; i ++ ) {        if ( s[x][i] ) check(s[x][i]) ;    }}void dfs ( int x ) {    if ( inq[x] ) return ;    inq[x] = 1 ;    vis[x] = 1 ;    int i, u ;    for ( i = 0 ; i < 2 ; i ++ ) {        if ( s[x][i] ) {            if ( s[x][i][vis] ) {                puts("TAK") ;                exit(0) ;            } else if ( !s[x][i][tim] ) dfs(s[x][i]) ;        }    }    vis[x] = 0 ;}int main() {    int i, j, k ;    scanf ( "%d", &n ) ;    h = ++tot ;    for ( i = 1 ; i <= n ; i ++ ) {        scanf ( "%s", pat+1 ) ;        insert() ;    }    calc() ;    vis[1] = 1 ;    dfs(1) ;    puts("NIE") ;    return 0 ;}
原创粉丝点击