AC自动机模板

大白书上的模板

 

HDU2222模板题目

/***************************
* 智商啊-。-  终于看懂AC自动机了T_T
* Date:2014/01/10
* author:crazy_石头
* algorithm:Aho-Corasick 自动机
* AC自动机=KMP+Trie
* AC自动机主要就3个部分:   
* 1 建树:和普通字典树一样
* 2 建失败指针:
* ///根结点的失败指针指向自己
* ///每个结点的失败指针是从父节点的失败指针指向的结点的子结点中寻找与这个结点相同的结点
* ///如果找不到,就向上回溯直到根节点
* 同时 顺手把不存在的边都给补上,顺手建last数组
* 3 模式匹配:因为失配函数的时候顺手把不存在的边都给补上了,直接顺着失配边走下去就好了
*************************************/

 

#include <iostream>
#include <cstdio>
#include <cstring>
#include <queue>

using namespace std;

const int maxn=550000;

struct AC_auto
{
    int chd[maxn][26],v[maxn],f[maxn],last[maxn],sz,ans;
    void init()
    {
        sz=1;ans=0;
        memset(v,0,sizeof(v));
        memset(f,0,sizeof(f));
        memset(chd[0],0,sizeof(chd[0]));
    }
    void insert(char* p)
    {
        int cur=0;
        for(;*p;p++)
        {
            if(!chd[cur][*p-'a'])
            {
                memset(chd[sz],0,sizeof(chd[sz]));
                chd[cur][*p-'a']=sz++;
            }
            cur=chd[cur][*p-'a'];
        }
        v[cur]++;
    }
    bool query(char* p)
    {
        int cur=0;
        for(;*p;p++)
        {
            if(!chd[cur][*p-'a']) break;
            cur=chd[cur][*p-'a'];
        }
        return v[cur]&&(!(*p));
    }
    int getFail()
    {
        queue<int> q;
        f[0]=0;
        for(int c=0;c<26;c++)
        {
            int u=chd[0][c];
            if(u)
            {
                f[u]=0; q.push(u); last[u]=0;
            }
        }
        while(!q.empty())
        {
            int r=q.front(); q.pop();
            for(int c=0;c<26;c++)
            {
                int u=chd[r][c];
                if(!u){ chd[r][c]=chd[f[r]][c];continue;}///....
                q.push(u);
                int vv=f[r];
                while(vv&&!chd[vv][c]) vv=f[vv];
                f[u]=chd[vv][c];
                last[u]=v[f[u]] ? f[u] : last[f[u]];
            }
        }
    }
    void solve(int j)
    {
        if(!j) return;
        if(v[j])
        {
            ans+=v[j];
            v[j]=0;
        }
        solve(last[j]);
    }
    void find(char* T)
    {
        int n=strlen(T),j=0;
        getFail();
        for(int i=0;i<n;i++)
        {
            //while(j&&!chd[j][*T-'a']) j=f[j];
            j=chd[j][T[i]-'a'];
            if(v[j]) solve(j);
            else if(last[j]) solve(last[j]);
        }
    }
}ac;

int main()
{
    int t,n;
    char dic[100],str[1100000];
    scanf("%d",&t);
    while(t--)
    {
        ac.init();
        scanf("%d",&n);
        while(n--)
        {
            scanf("%s",dic);
            ac.insert(dic);
        }
        scanf("%s",str);
        ac.find(str);
        printf("%d\n",ac.ans);
    }
    return 0;
}


 

你可能感兴趣的:(AC自动机模板)