[explanation] HDU-2222 Keywords Search

Keywords: C++

Title Link: HDU-2222 Or Vjudge

Brief description:

The establishment of ac automata, in which the insertion process uses the dictionary tree to deal with the backtracking array (also known as the failure array) process is a widely used STL queue. The process of ac automata is still in writing.

This is the first question of learning ac automata. If Wa is concerned, it should be noted how the string end tag is marked. It can't just record, it has to count. Wa several times

my codes:

 

#include <algorithm>
#include <iostream>
#include <cstring>
#include <string>
#include <cstdio>
#include <queue>
#define set(a) memset(a,0,sizeof(a))
#define set_b(a) memset(a,false,sizeof(a))
using namespace std;
const int M=5e5+10;
const int N=1e6+10;

int tree[M][26];/**< tree[u][i]  Represents the node value of the i son of node u */
int ed[M];/**< The end mark of string is flexible to use, and the question should be counted */
int nxt[M];/**< Backtracking array */
char s[N];/**< Text string */
int tot;/**< Node number */


struct ac_auto
{
    void pre_set()/**< Initialization */
    {
        tot=1;
        set(ed);
        set(tree);
        set(nxt);
    }
    void build(char str[])/**< Basic insert operation */
    {
        int len=strlen(str);
        int u=1;
        for(int i=0; i<len; i++)
        {
            int v=str[i]-'a';
            if(!tree[u][v])
                tree[u][v]=++tot;
            u=tree[u][v];
        }
//    printf("%d\n",u);
        ed[u]++;
    }
    void deal_next()/**< Processing the backtracking array, a virtual zero node is used, and the following two lines represent all its sons and No. 1 edge building */
    {
        for(int i=0; i<26; i++)
            tree[0][i]=1;
        queue<int> q;
        while(!q.empty())
            q.pop();
        nxt[1]=0;/**< Node one goes back to zero */
        q.push(1);/**< When node No. 0 is used, press in 1 first. If you don't set the zero, all the sons who press in 1. Two, pay attention to the difference */
        while(!q.empty())
        {
            int u=q.front();
            q.pop();
            for(int i=0; i<=25; i++)
            {
                if(!tree[u][i])/**< u No son */

                    tree[u][i]=tree[nxt[u]][i];
                                                  /** \brief u And its i son. With this sentence, every node will
                                                            If there are 26 sons, there will be no node. If there is no i son, i will continue to search
                                                            Father's backtracking node information is a problem.
                                                      \return
                                                    */
                else
                {
                    nxt[tree[u][i]]=tree[nxt[u]][i];/**< u My son's nxt value i s my son's number of next[u] */
//                printf("nxt[%d]=%d\n",tree[u][i],tree[nxt[u]][i]);
                    q.push(tree[u][i]);
                }
//            printf("%d Of %c Son No.:%d\n",u,'a'+i,tree[u][i]);
            }
        }
    }
    int search()
    {
        int len=strlen(s);
        int ans=0;
        int u=1,v;
        for(int i=0; i<len; i++)
        {
            v=s[i]-'a';
            u=tree[u][v];
            int tp=u;
            while(tp>1&&ed[tp])
            {
                ans+=ed[tp];
                ed[tp]=0;
                tp=nxt[tp];
            }
        }
        return ans;
    }
};

int main()
{
    int T,n;
    cin>>T;
    while(T--)
    {
        ac_auto().pre_set();
        cin>>n;
        while(n--)
        {
            char str[55];
            scanf("%s",str);
            ac_auto().build(str);
        }
        scanf("%s",s);
        ac_auto().deal_next();
        int ans=ac_auto().search();
        cout<<ans<<endl;
    }
    return 0;
}

Posted by madox on Sat, 25 Jan 2020 08:18:24 -0800