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;

}

你可能感兴趣的:(search)