HDOJ_2222 AC自动机

这个题网上有很多讲解,感觉在看这个题之前最好先去看看KMP ,不然看再多的讲解,可能也不能理解构造失败指针的意义是什么。在KMP中NEXT的作用是党不匹配时指针后移,而这个后移量则是通过 NEXT 来控制的,这个题里面 构造 失败指针的意义 和NEXT的作用一样,就是前后移动指针的。这个懂了,再看看别人的图示,就会明白构造的过程,其中 我理解的是用 广度优先 遍历的。大家可以看看这个文章http://www.cppblog.com/mythit/archive/2009/04/21/80633.html 里面讲解的很详细。

代码:

#include<stdio.h>
#include<queue>
using namespace std;
typedef struct node
{
    int count;
    node *fail;
    node *next[26];
}node;
node *h;
void insert(char *key)
{
    int i;
    node *p;
    char *q;
    p=h;
    q=key;
    while(*q)
    {
        if(p->next[*q-'a']==NULL)
        {
            p->next[*q-'a']=(node*)malloc(sizeof(node));
            p->next[*q-'a']->count=0;
            p->next[*q-'a']->fail=NULL;
            for(i=0;i<26;++i)
                p->next[*q-'a']->next[i]=NULL;
        }
        p=p->next[*q-'a'];
        q++;
    }
    p->count++;
}
void makefail()
{
    int i;
    node *fa,*so,*an;
    queue<node*>qu;
    qu.push(h);
    while(!qu.empty())
    {
        fa=qu.front();
        qu.pop();
        for(i=0;i<26;++i)
            if(fa->next[i]!=NULL)
            {
                if(fa==h)
                    fa->next[i]->fail=h;
                else
                {
                    so=fa->next[i];
                    an=fa->fail;
                    while(an!=NULL&&an->next[i]==NULL)
                        an=an->fail;
                    if(an==NULL)
                        so->fail=h;
                    else
                        so->fail=an->next[i];
                }
                qu.push(fa->next[i]);
            }
    }
}
int find(char *des)
{
    int sum=0,at,i;
    node *p,*q;
    p=h;
    i=0;
    while(des[i])
    {
        at=des[i]-'a';
        while(p->next[at]==NULL&&p!=h)
            p=p->fail;
        p=p->next[at];
        if(p==NULL)
            p=h;
        q=p;
        while(q!=h&&q->count)
        {
            sum+=q->count;
            q->count=0;
            q=q->fail;
        }
        i++;
    }
    return sum;
}
int main()
{
    int T,i,n;
    char str[55],des[1000005];
    h=(node*)malloc(sizeof(node));
    scanf("%d",&T);
    while(T--)
    {
        h->fail=NULL;
        for(i=0;i<26;++i)
            h->next[i]=NULL;
        scanf("%d",&n);
        while(n--)
        {
            scanf("%s",str);
            insert(str);
        }
        makefail();
        scanf("%s",des);
        printf("%d\n",find(des));
    }
    return 0;
}

 

posted @ 2012-08-17 10:20  煮人为乐  阅读(826)  评论(0编辑  收藏  举报