Luo Gu --P3808 [template] AC automatic machine ( "fake" Simple version)

If you want to work out this problem, you need to first understand the two knowledge points:

1, the tree structure dictionary

2, KMP algorithm (i.e. fail configuration pointer)

For a trie, you can look at this big brother:

https://www.cnblogs.com/TheRoadToTheGold/p/6290732.html

For KMP, you can look at this big brother:

https://www.cnblogs.com/SYCstudio/p/7194315.html#4255259  (highly recommended !!!!)

Step :( code for the first two steps are necessary automaton AC)

1, using the provided pattern strings trie structure

2, the configuration of the pointer fail, i.e., the current node pointer fail = fail its parent node pointed to the same child node pointed. For value is defined fail pointer FIFO queue queue to borrow ideas (here is the difficulty, please do not understand the comments section)

3, according to the meaning of the questions constructor query function that returns the number ans

AC Code:

#include <bits / STDC ++ H.>
 the using  namespace STD; 
typedef Long  Long LL;
 const  int MAXN = 1e6 + . 5 ;
 char T [MAXN], S [MAXN];
 struct Tree 
{ 
    int Fail; // mismatch pointer 
    int Son [ 26 ]; // a node has a child node up to 26 
    int NUM; // marked as the end of this node 
} the DFA [MAXN]; // trie 
int CNT = 0 ;
 void Build ( String S) 
{ 
    int now = 0; // trie current pointer 
    for ( int I = 0 ; I <s.length (); ++ I) 
    { 
        IF (the DFA [now] .son [S [I] - ' A ' ] == 0 ) / / tree child node is not 
            the DFA [now] .son [S [I] - ' a ' ] = CNT ++; // add a node 
        now the DFA = [now] .son [S [I] - ' a ' ]; // downwardly configured 
    } 
    the DFA [now] .num + = . 1 ; // closing tag word 
}
 void Get_fail () // constructor pointer fail
{ 
    Queue < int > Q;
     for ( int I = 0 ; I < 26 is ; ++ I) 
    { 
        IF (the DFA [ 0 !] .Son [I] = 0 ) 
        { 
            the DFA [the DFA [ 0 ] .son [I] ] .fail = 0 ; // points to the root node, a second layer 
            Q.push (the DFA [ 0 ] .son [I]); // pressed into queue 
        } 
    } 
    the while (! Q.empty ()) 
    { 
        int U = Q.front (); 
        Q.pop (); 
        for (int I = 0 ; I < 26 is ; I ++)   // back layer 
        {
             IF ! (the DFA [U] .son [I] = 0 ) // if this node exists 
            { 
                the DFA [the DFA [U] .son [ I]] fail. = the DFA [the DFA [U] .fail] .son [I]; // same child node corresponding to the value of fail to parent node of the node 
                Q.push (DFA [u] .son [ I]); // queued 
            }
             the else  // If this node does not exist 
            { 
                the DFA [U] .son [I] = the DFA [the DFA [U] .fail] .son [I];   // current node's child nodes points to the current node's child nodes fail 
            } 
        } 
    } 
}
int query(char *s)
{
    int len=strlen(s);
    int now=0,ans=0;
    for(int i=0;i<len;++i)
    {
        now=DFA[now].son[s[i]-'a'];
        for(int t=now;t!=0&&DFA[now].num!=-1;++t)
            {
                if(DFA[now].num>0) //表示存在结尾
                    ans+=DFA[now].num;
                 DFA[t].num=-1; //标记已访问过
            }
        }
    return ans;
}


int main()
{
    int n;
    scanf("%d",&n);
    for(int i=0;i<n;i++)
    {
        scanf("%s",t);
        build(t);
    }
    Get_fail();
    scanf("%s",s);
    int ans=query(s);
    printf("%d\n",ans);
    return 0;
}

AC automaton difficult to understand, forgive me lazy, did not give us a satisfactory resolution, but we have a problem I can comment area private, I'll try to answer them in!

 

Guess you like

Origin www.cnblogs.com/acmer-hmin/p/11761622.html