AC自动机入门

来源:互联网 发布:软件企业认定机构 编辑:程序博客网 时间:2024/05/11 02:27

AC自动机的模板题。

HDU3065 病毒侵袭持续中

题意:给定n个字符串和一段文本,统计每个字符串在文本中分别出现的次数。

注意点:这里输入单词的时候给每个单词分布一个id,然后在统计次数的时候根据id增加数组的次数就可以了。(这里用kuangbin大神的模板)

code:

#include <iostream>#include <string.h>#include <stdio.h>#include <queue>using namespace std;char t[1005][55],s[2000005];const int ma=50010,kd=26;int ans[1005];struct Trie{    int next[ma][kd],fail[ma],en[ma];    int root,L,id;    int newnode()    {        for(int i=0; i<kd; ++i)            next[L][i]=-1;        en[L++]=0;        return L-1;    }    void init()    {        L=0;        id=0;        root=newnode();    }    void Insert(char buf[])    {        int len=strlen(buf);        int now=root;        for(int i=0; i<len; ++i)        {            if(next[now][buf[i]-'A']==-1)                next[now][buf[i]-'A']=newnode();            now=next[now][buf[i]-'A'];        }        en[now]=++id;    }    void build()    {        queue<int> q;        fail[root]=root;        for(int i=0; i<26; ++i)        {            if(next[root][i]==-1)                next[root][i]=root;            else            {                fail[next[root][i]]=root;                q.push(next[root][i]);            }        }        while(!q.empty())        {            int now=q.front();            q.pop();            for(int i=0; i<26; ++i)                if(next[now][i]==-1)                    next[now][i]=next[fail[now]][i];                else                {                    fail[next[now][i]]=next[fail[now]][i];                    q.push(next[now][i]);                }        }    }    void query(char buf[])    {        memset(ans,0,sizeof(ans));        int len=strlen(buf);        int now=root;        for(int i=0; i<len; ++i)        {            if(buf[i]>='A'&&buf[i]<='Z')            {                now=next[now][buf[i]-'A'];                int temp=now;                while(temp!=root)                {                    ans[en[temp]]++;                    temp=fail[temp];                }            }            else now=root;        }    }};Trie ac;int main(){    int n;    while(scanf("%d",&n)!=EOF)    {        ac.init();        for(int i=1; i<=n; ++i)   //这里字符串的下标要从1开始,因为前面分布是 ++id        {            scanf("%s",t[i]);            ac.Insert(t[i]);        }        ac.build();        scanf("%s",s);        ac.query(s);        for(int i=1; i<=n; ++i)          {            if(ans[i])                printf("%s: %d\n",t[i],ans[i]);        }    }    return 0;}








原创粉丝点击