Cattle off the word ac automata

Topic links: https://ac.nowcoder.com/acm/problem/20443

Thinking: This question gives a lot of words, now ask the total number of each word appears in all word. First step is to build a dictionary tree, and then fail to build pointer, and finally the whole grain dictionary tree node traversal again.

  The number of times we can put through each node at the time of construction trie first calculated, because each node of the trie represents a different string (path from the root to this node only), so we after the number of times each node of the trie beginning calculated that the string represented by the node for all the input word prefix number.

  For example, we have the word aa, aab, aba, it is assumed that a string consisting of the trie from the root to a certain node u is aa, then we have built trie, the number of passes the point u is 2, because in these aa word as a prefix number that appears is 2 ( AA , AA b, aba).

  We then build pointer fail, fail [u] represents the fact from the root node to fail [u] This configuration of the prefix and the length of the same node u to the end of the extension is the same, we have as a prefix string occurring the number of counted out, as long as we each prefix in whole grain calculated as the number of trees other string suffix, then the total number of the string that appears is the sum of two times. And the total number of times we can rely fail to obtain a pointer to linear, when we fail to build a pointer, we must be the first to traverse each prefix, so this prefix will certainly appear first in the queue, the position will be ranked in the queue in other string -> (suffix these strings, there is what we call a prefix) in front. So we can reverse traverse through all the nodes in the queue, the number of statistics for each point in the direction of superposition fail pointer. Eventually we can get all the trie prefix number that appears in the input word.

Code:

#include<iostream>
#include<cstring>
#include<algorithm>
#include<queue>
#include<map>
#include<stack>
#include<cmath>
#include<vector>
#include<set>
#include<cstdio>
#include<string>
#include<deque> 
using namespace std;
typedef long long ll;
#define eps 1e-8
#define INF 0x3f3f3f3f
#define maxn 2000005
intQ [MAXN];
 int TOT = 0 , CNT = 0 , n-; 
 int Fail [MAXN], Trie [MAXN] [ 27 ], NUM [MAXN], pos [MAXN]; // NUM array record number, pos array record the end of each word node number in the dictionary tree 
char S [MAXN];
 void INSERT ( int len, int index) {
     int the root = 0 ;
     for ( int I = 0 ; I <len; I ++ ) {
         int C = S [I] - ' A ' ;
         IF (Trie [the root] [C] == 0 ) 
        Trie [the root] [C] = ++CNT; 
        the root = Trie [the root] [C]; 
        NUM [the root] ++; // number num [i] records string ending node I (prefix) appears 
    } 
    POS [index] = the root; // record at the word ending node number 
}
 void build_fail () { // build fail pointers 
    for ( int I = 0 ; I < 26 is ; I ++ ) {
         IF (Trie [ 0 ] [I]) { 
            fail [Trie [ 0 ] [ I]] = 0 ; 
            Q [TOT ++] = Trie [ 0 ] [I]; 
        } 
    } 
    int now=0;
    while(now<tot){
        int u=q[now++];
        for(int i=0;i<26;i++){
            if(trie[u][i]){
                fail[trie[u][i]]=trie[fail[u]][i];
                q[tot++]=trie[u][i];
            }else{
                trie[u][i]=trie[fail[u]][i];
            }
        }
    }
}
int main()
{
    scanf("% D " , & n-);
     for ( int I = 0 ; I <n-; I ++ ) { 
        Scanf ( " % S " , S);
         int len = strlen (S); 
        INSERT (len, I); 
    } 
    build_fail ( ); 
    for ( int I = tot- . 1 ; I> = 0 ; i--) NUM [fail [Q [I]]] + NUM = [Q [I]]; // number of times in the direction of superposition of points fail 
    for ( int I = 0 ; I <n-; I ++) the printf ( " % D \ n- " , NUM [POS [I]]); // previously recorded after the end position of each word, where direct output
    return 0;
}

 

Guess you like

Origin www.cnblogs.com/6262369sss/p/11680775.html