lightoj 1427 Substring Frequency (II) (ac自动机)

来源:互联网 发布:lesscss1.4.0.min.js 编辑:程序博客网 时间:2024/05/22 06:10

lightoj 1427 Substring Frequency (II) (ac自动机)

题意:求每个模式串在母串中出现的次数。

解题思路:ac自动机(显然)。类似模板题,但是这题查询的时候不能一直沿着fail边走,而是要用到fail树上的拓扑,最后dp往上推。

#include<stdio.h>#include<string.h>#include<algorithm>#include<queue>using namespace std ;const int maxn = 500*500 ;char s1[1111111] , s2[maxn] ;struct ac_auto {    int c[maxn][26] , tot , fail[maxn] ;    int st[maxn] , top , val[maxn] ;    int pos[maxn] ;    inline int new_node () {        int i ;        val[tot] = fail[tot] = 0 ;        memset(c[tot], 0, sizeof(c[tot]));        return tot ++ ;    }    void init () {        tot = top = 0 ;        new_node () ;    }    void insert ( char *s , int id ) {        int now = 0 ;        for ( ; *s ; s ++ ) {            int k = *s - 'a' ;            if ( !c[now][k] ) c[now][k] = new_node () ;            now = c[now][k] ;        }        pos[id] = now ;    }    void get_fail () {            queue<int> Q ;        int u = 0 , i , j ,e ;        for ( i = 0 ; i < 26 ; i ++ ) {            if ( c[u][i] ) Q.push ( c[u][i] ) ;          //  st[++top] = c[i][u] ;        }        while ( !Q.empty () ) {            u = Q.front () , Q.pop () ;            for ( i = 0 ; i < 26 ; i ++ ) {                if ( c[u][i] ) {                    e = c[u][i] ;                    j = fail[u] ;                    fail[e] = c[j][i];                    Q.push ( e ) ;                    st[++top] = e ;                }                else c[u][i] = c[fail[u]][i] ;            }        }    }    void solve ( char *s , int n ) {        int now = 0 ;        int i ;        for ( ; *s ; s ++ ) {            int k = *s - 'a' ;            now = c[now][k] ;            val[now] ++ ;        }        while ( top ) {            int p = st[top] ;            val[fail[p]] += val[p] ;            top -- ;        }        for ( i = 1 ; i <= n ; i ++ )            printf ( "%d\n" , val[pos[i]] ) ;    }} ac ;int main () {    int cas , ca = 0 , n , i ;    scanf ( "%d" , &cas ) ;    while ( cas -- ) {        scanf ( "%d" , &n ) ;        scanf ( "%s" , s1 ) ;        ac.init () ;        for ( i = 1 ; i <= n ; i ++ ) {            scanf ( "%s" , s2 ) ;            ac.insert ( s2 , i ) ;        }        ac.get_fail () ;        printf ( "Case %d:\n" , ++ ca ) ;        ac.solve ( s1 , n ) ;    }}