蒟蒻不想取名字

这个博客可以拿来放模板诶~

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自动机会无限循环,反之一定会在有限的时间内结束。

/**************************************************************

    Problem: 2938

    User: idy002

    Language: C++

    Result: Accepted

    Time:40 ms

    Memory:2316 kb

****************************************************************/

 

#include <cstdio>

#include <cstring>

#include <cstdlib>

#include <queue>

#define maxn 60010

using namespace std;

 

int son[maxn][2], fail[maxn], ikey[maxn], ntot;

int vis[maxn], cir[maxn];

char str[maxn];

 

void insert( const char *P ) {

    int n=strlen(P);

    int u=0;

    for( int i=0; i<n; i++ ) {

        int c=P[i]-'0';

        if( !son[u][c] ) son[u][c] = ++ntot;

        u=son[u][c];

    }

    ikey[u] = true;

}

void build_fail() {

    queue<int> qu;

    for( int c=0; c<2; c++ ) {

        int v=son[0][c];

        if( !v ) continue;

        qu.push( v );

        fail[v] = 0;

    }

    while( !qu.empty() ) {

        int u=qu.front();

        qu.pop();

        for( int c=0; c<2; c++ ) {

            int v=son[u][c];

            int w=fail[u];

            if( !v ) {

                son[u][c] = son[fail[u]][c];

                continue;

            }

            while( w && !son[w][c] ) w=fail[w];

            fail[v] = son[w][c];

            ikey[v] |= ikey[fail[v]];

            qu.push( v );

        }

    }

}

void dfs( int u ) {

    vis[u] = true;

    for( int c=0; c<2; c++ ) {

        int v=son[u][c];

        if( cir[v] || ikey[v] ) continue;

        if( !vis[v] )

            dfs(v);

        else {

            printf( "TAK\n" );

            exit(0);

        }

    }

    cir[u] = true;

}

int main() {

    int n;

    scanf( "%d", &n );

    for( int i=0; i<n; i++ ) {

        scanf( "%s", str );

        insert( str );

    }

    build_fail();

    dfs( 0 );

    printf( "NIE\n" );

}


评论