您的位置:首页 > 其它

AC自动机模板

2014-01-10 22:00 295 查看
大白书上的模板



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;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: