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\n" );
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\n" );
80 }
View Code

 

posted @ 2015-03-14 20:12  idy002  阅读(212)  评论(0编辑  收藏  举报