hdu 2222 Keywords Search(AC自动机)

来源:互联网 发布:unity3d ios 编辑:程序博客网 时间:2024/04/30 21:52

AC自动机,暑假的时候一直没弄明白这个算法。今天又重新看了一下,貌似有点儿懂了。

详细的介绍看这里:点击打开链接。

首先是将模式串建成一个字典树,然后用一次bfs()来构造失败指针。需要注意的地方是,失败指针并不只是同样的字符指向更高层数的同样的字符,而是新的字符所在的串的前缀应该是当前字符所在的串的后缀。失败指针指向的字符的位置比当前字符所在的位置靠前也是这个原因。

在扫描过程中,当前字符扫描失败,就要回到root节点重新开始扫描。

还是有很多地方没理解好。

#include<stdio.h>#include<string.h>#include<malloc.h>#define N 500005char s[N*2],ss[55];struct node{    node *fail;    node *next[27];    int count;}*a[N];node *root;void Init(node *s){    s->count=0;    s->fail=NULL;    for(int i=0;i<26;i++)        s->next[i]=NULL;    return ;}void InsertTree(char *s){    int ln=strlen(s);    node *p=root,*q;    for(int i=0;i<ln;i++)    {        int t=s[i]-'a';        if(p->next[t]!=NULL)            p=p->next[t];        else        {            q=(node *)malloc(sizeof(node));            Init(q);            p->next[t]=q;            p=q;        }        if(i==ln-1) p->count++;    }    return ;}void bfs(){    int head,tail;    head=tail=0;    a[tail++]=root;    while(head!=tail)    {        node *p=a[head++];        for(int i=0;i<26;i++)        {            if(p->next[i]!=NULL)            {                if(p==root)                    p->next[i]->fail=root;                else                {                    node *temp;                    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;                }                a[tail++]=p->next[i];            }        }    }    return ;}int Que(){    int ln=strlen(s);    int cnt=0;    node *p=root;    for(int i=0;i<ln;i++)    {        int t=s[i]-'a';        while(p->next[t]==NULL&&p!=root)            p=p->fail;        p=p->next[t];        if(p==NULL) p=root;        node *temp=p;        while(temp!=NULL&&temp->count!=-1)        {            cnt+=temp->count;            temp->count=-1;            temp=temp->fail;        }    }    return cnt;}int main(){    int T;    scanf("%d",&T);    while(T--)    {        int n;        scanf("%d",&n);        getchar();        root=(node *)malloc(sizeof(node));        Init(root);        while(n--)        {            gets(ss);            InsertTree(ss);        }        bfs();        gets(s);        printf("%d\n",Que());    }    return 0;}


原创粉丝点击