hdu2222 AC自动机

字典树也可以做。

#include<stdio.h>
#include<string.h>
#include<stdlib.h>
#define maxn 1000010
struct ac_mation
{
    ac_mation *fail;//失败指针
    ac_mation *next[26];//26个字母
    int flag;//标记是否为最后一个点
    init(){//函数初始化
        flag=0;
        fail=NULL;
        for(int i=0;i<26;i++)
            next[i]=NULL;
    }
}*q[500010];
ac_mation *root;
char s[maxn],str[60];
int n,head,tail;
void insert(char *str)
{
    int i,j,len=strlen(str);
    ac_mation *p=root,*qq;
    for(i=0;i<len;i++)
    {
        int id=str[i]-'a';
        if(p->next[id]==NULL)
        {
            qq=new ac_mation;
            qq->init();
            p->next[id]=qq;
        }
        p=p->next[id];
    }
    p->flag++;
}
void getfail()//构建失败指针
{
    int i;
    q[tail++]=root;
    while(head!=tail)//bfs
    {
        ac_mation *p=q[head++];
        ac_mation *temp=NULL;
        for(i=0;i<26;i++)
        {
            if(p->next[i]!=NULL)
            {
                if(p==root)//第一个元素的fail指针必须是root
                    p->next[i]->fail=root;
                else
                {
                    temp=p->fail;//失败指针
                    while(temp!=NULL)//如果找到了
                    {
                        if(temp->next[i] != NULL)//找到
                        {
                            p->next[i]->fail = temp->next[i];
                            break;
                        }
                        temp=temp->fail;
                    }
                    if(temp==NULL)//找不到
                        p->next[i]->fail=root;
                }
                q[tail++]=p->next[i];
            }
        }
    }
}
void query(char *s)
{
    int ans=0;
    int i,j,len=strlen(s);
    ac_mation *p=root,*temp;
    for(i=0;i<len;i++)
    {
        int id=s[i]-'a';
        while(p->next[id]==NULL&&p!=root)//跳转到失败指针
            p=p->fail;
        p=p->next[id];
        if(p==NULL)
            p=root;
        temp=p;
        while(temp!=root&&temp->flag!=-1)
        {
            ans+=temp->flag;
            temp->flag=-1;
            temp=temp->fail;
        }
    }
    printf("%d\n",ans);
}
void freeac_mation(ac_mation *root)
{
    int i;
    for(i=0;i<26;i++)
    {
        if(root->next[i])
            freeac_mation(root->next[i]);
    }
    free(root);
}
int main()
{
    int i,t,j;
    scanf("%d",&t);
    while(t--)
    {
        head=tail=0;
        root=new ac_mation;
        root->init();
        scanf("%d",&n);
        for(i=0;i<n;i++)
        {
            scanf("%s",str);
            insert(str);
        }
        getfail();
        scanf("%s",s);
        query(s);
        freeac_mation(root);
    }
}

 

posted @ 2015-08-18 11:03  sweat123  阅读(158)  评论(0编辑  收藏  举报