HDOJ 2222 Keywords Search (AC自动机)

题意:给n个单词和一个文本,求有多少个单词出现在文本中。

据说这题是AC自动机的模版题。这题也是我写的第一个AC自动机的题。

View Code
#include <stdio.h>
#include <string.h>
#include <queue>
using namespace std;
#define LEN 55
#define N 10010
int n,node;
int next[N*LEN][26];
int cnt[N*LEN];
int fail[N*LEN];
void init()
{
    memset(next[0],0,sizeof(next[0]));
    node=1;
}
void add(int cur,int k)
{
    memset(next[node],0,sizeof(next[node]));
    cnt[node]=0;
    next[cur][k]=node++;
}
void insert(char s[])
{
    int i,k,cur;
    for(i=cur=0;s[i];i++)
    {
        k=s[i]-'a';
        if(!next[cur][k])   add(cur,k);
        cur=next[cur][k];
    }
    cnt[cur]++;
}
void build()
{
    int cur,nxt,k,tmp;
    queue<int> q;

    fail[0]=0;
    q.push(0);

    while(!q.empty())
    {
        cur=q.front(),q.pop();
        for(k=0;k<26;k++)
        {
            nxt=next[cur][k];
            if(!nxt)    continue;

            if(cur==0)  fail[nxt]=0;

            else
            {
                for(tmp=fail[cur];!next[tmp][k] && tmp;tmp=fail[tmp]);
                fail[nxt]=next[tmp][k];
            }

            q.push(nxt);
        }
    }
}
int match(char s[])
{
    int i,k,cur,ans=0;
    for(cur=i=0;s[i];i++)
    {
        k=s[i]-'a';
        for(;next[cur][k]==0 && cur;cur=fail[cur]);
        if(next[cur][k])    cur=next[cur][k];

        int tmp=cur;
        while(tmp)
        {
            ans+=cnt[tmp];
            cnt[tmp]=0;
            tmp=fail[tmp];
        }
    }
    return ans;
}
int main()
{
    int k;
    char tmp[LEN];
    char t[1000001];
    scanf("%d",&k);
    while(k--)
    {
        scanf("%d",&n);
        init();
        for(int i=0;i<n;i++)
        {
            scanf("%s",tmp);
            insert(tmp);
        }
        build();
        scanf("%s",t);
        printf("%d\n",match(t));
    }
    return 0;
}
原文地址:https://www.cnblogs.com/algorithms/p/2617130.html