zoukankan      html  css  js  c++  java
  • bzoj 2938

    收获:

      1、AC自动机可以在建立fail时将一些不存在的儿子指针指向对应的位置。

      2、判断环时不要想当然地写个这样的版本:

    bool dfs( int u ) {
        if( vis[u] ) return true;
        vis[u] = true;
        for( int t=0; t<g[u].size(); t++ ) {
            int v=g[u][t];
            if( dfs(v) ) return true;
        }
        vis[u] = false;
        return false;
    }

    它不是O(n)的,然后我就T了,搞了好久才弄好。

      3、存在一个无限长的不与给定pattern匹配的text,那么在该text上跑ac自动机会无限循环,反之一定会在有限的时间内结束。

     1 /**************************************************************
     2     Problem: 2938
     3     User: idy002
     4     Language: C++
     5     Result: Accepted
     6     Time:40 ms
     7     Memory:2316 kb
     8 ****************************************************************/
     9  
    10 #include <cstdio>
    11 #include <cstring>
    12 #include <cstdlib>
    13 #include <queue>
    14 #define maxn 60010
    15 using namespace std;
    16  
    17 int son[maxn][2], fail[maxn], ikey[maxn], ntot;
    18 int vis[maxn], cir[maxn];
    19 char str[maxn];
    20  
    21 void insert( const char *P ) {
    22     int n=strlen(P);
    23     int u=0;
    24     for( int i=0; i<n; i++ ) {
    25         int c=P[i]-'0';
    26         if( !son[u][c] ) son[u][c] = ++ntot;
    27         u=son[u][c];
    28     }
    29     ikey[u] = true;
    30 }
    31 void build_fail() {
    32     queue<int> qu;
    33     for( int c=0; c<2; c++ ) {
    34         int v=son[0][c];
    35         if( !v ) continue;
    36         qu.push( v );
    37         fail[v] = 0;
    38     }
    39     while( !qu.empty() ) {
    40         int u=qu.front();
    41         qu.pop();
    42         for( int c=0; c<2; c++ ) {
    43             int v=son[u][c];
    44             int w=fail[u];
    45             if( !v ) {
    46                 son[u][c] = son[fail[u]][c];
    47                 continue;
    48             }
    49             while( w && !son[w][c] ) w=fail[w];
    50             fail[v] = son[w][c];
    51             ikey[v] |= ikey[fail[v]];
    52             qu.push( v );
    53         }
    54     }
    55 }
    56 void dfs( int u ) {
    57     vis[u] = true;
    58     for( int c=0; c<2; c++ ) {
    59         int v=son[u][c];
    60         if( cir[v] || ikey[v] ) continue;
    61         if( !vis[v] )
    62             dfs(v);
    63         else {
    64             printf( "TAK
    " );
    65             exit(0);
    66         }
    67     }
    68     cir[u] = true;
    69 }
    70 int main() {
    71     int n;
    72     scanf( "%d", &n );
    73     for( int i=0; i<n; i++ ) {
    74         scanf( "%s", str );
    75         insert( str );
    76     }
    77     build_fail();
    78     dfs( 0 );
    79     printf( "NIE
    " );
    80 }
    View Code
  • 相关阅读:
    NYOJ 625 笨蛋的难题(二)
    NYOJ 102 次方求模
    ZJU Least Common Multiple
    ZJUOJ 1073 Round and Round We Go
    NYOJ 709 异形卵
    HDU 1279 验证角谷猜想
    BNUOJ 1015 信息战(一)——加密程序
    HDU 1202 The calculation of GPA
    "蓝桥杯“基础练习:字母图形
    "蓝桥杯“基础练习:数列特征
  • 原文地址:https://www.cnblogs.com/idy002/p/4338166.html
Copyright © 2011-2022 走看看