hdu 2222 Keywords Search

Keywords Search

AC自动机典型模板

/*
写于13年4月1日,AC自动机练习
参考的别人代码,
个人觉得自动机就是trie 外加kmp的有机组合
*/

#include<string.h>
#include <iostream>
#include <stdio.h>
using namespace std;
const int maxn=10010*50;
char str[1000010];//文本串
struct node{
    node *fail;
    node *next[26];
    int flag;
    node()
    {
        fail=NULL;
        flag=0;
        for(int i=0;i<26;i++)
        {
            next[i]=NULL;
        }
    }

}*root;
node *q[maxn];//队列

void insert(char *s)//建树
{
    node *p=root;
    int k=0;
    while(s[k]!='\0')
    {
        int temp=s[k]-'a';
        if(p->next[temp]==NULL)
            p->next[temp]=new node;
        p=p->next[temp];
        k++;
    }
    p->flag++;//单词个数
}
void build_fail()//建立失败指针 BFS
{
    node *p,*temp;
    int head=0,tail=0;
    q[tail++]=root;
    while(tail^head)//队列中存在元素
    {
        p=q[head++];
        temp=NULL;
        for(int i=0;i<26;i++)
        {
            if(p->next[i]!=NULL)//对p的每个儿子寻找fail
            {
                if(p==root)//根的子节点的失败指针指向根节点
                {
                    p->next[i]->fail=root;
                }
                else
                {
                    temp=p->fail;//p的fail
                    while(temp!=NULL)//匹配成功或者temp为空
                    {
                        if(temp->next[i]!=NULL)
                        {
                            p->next[i]->fail=temp->next[i];//p的儿子与fail的儿子相同,匹配成功
                            break;
                        }
                        temp=temp->fail;
                    }
                    if(temp==NULL)//匹配失败,从头开始
                    {
                        p->next[i]->fail=root;
                    }
                }
                q[tail++]=p->next[i];//p的儿子入队
            }
        }
    }
}
int query()
{
    node *p,*temp;
    int k,ans=0;
    p=root;
    int len=strlen(str);
    for(int i=0;i<len;i++)
    {
        k=str[i]-'a';
       while(p->next[k]==NULL&&p!=root)//跳转失败指针
       {
           p=p->fail;
       }
        p=p->next[k];
        if(p==NULL)
            p=root;
        temp=p;
        //p不变,temp计算后缀
        //temp等于root时,后缀为空
        //temp->flag=-1时,有循环体知,后续fail->flag全部为-1
        while(temp!=root&&temp->flag!=-1)
        {
            ans+=temp->flag;
            temp->flag=-1;
            temp=temp->fail;
        }
    }
    return ans;
}
int main()
{
    char key[55];
    int ncase,num;
    scanf("%d",&ncase);
    while(ncase--)
    {
        scanf("%d",&num);
        //getchar();
        root=new node;
        while(num--)
        {
            scanf("%s",key);
            insert(key);
        }
        build_fail();
        scanf("%s",str);
        printf("%d\n",query());
    }
    return 0;
}

 

posted on 2013-04-02 20:57  行者1992  阅读(175)  评论(0编辑  收藏  举报