hdu 2222 keywords search (AC自动机 模板)

来源:互联网 发布:网络借贷监管细则全文 编辑:程序博客网 时间:2024/06/03 18:30

题目:http://acm.hdu.edu.cn/showproblem.php?pid=2222

我日,写错好多小细节,还差得远呢。。。

#include<stdio.h>#include<string.h>#include<stdlib.h>#define N 500010char str[1000010],keyword[51];int head,tail;typedef struct node{    struct node*fail;    struct node*next[26];    bool exist;    int count;}*trie,node;trie root;trie q[N];void creat(trie &p){    p=(trie)malloc(sizeof(node));    for(int i=0;i<26;i++)        p->next[i]=NULL;    p->exist=false;    p->count=0;    p->fail=NULL;             /*原来一切的根源在于root的fail没有初始化,日*/}void insert(trie p,char s[]){    int k=0 ;    while(s[k]!='\0'){        if(!p->next[s[k]-'a']){            trie q;            creat(q);            p->next[s[k]-'a']=q;        }        p=p->next[s[k]-'a'];        k++;    }    p->count++;}void build_ac(){                         /*建立fail指针,BFS*/    q[tail++]=root;    while(head!=tail){        node*p=q[head++];                  /*出队*/        node*temp=NULL;        for(int i=0;i<26;i++){            if(p->next[i]!=NULL){                if(p==root)                    p->next[i]->fail=root;   /*root下面的26的fail必指向root*/                else{                    temp=p->fail;                    while(temp!=NULL){                        if(temp->next[i]!=NULL){                            p->next[i]->fail=temp->next[i];                            break;               /*找到了就break*/                        }                        temp=temp->fail;/*如果它的fail指针下的26个都没有的话,就指向fail指针的fail再找一次,直到退到root就也能退出来了*/                    }                    if(temp==NULL)                        p->next[i]->fail=root;                }                q[tail++]=p->next[i];    /*入队*/            }        }    }}int query(trie p){    int index,len,result;    result=0;    len=strlen(str);    for(int i=0;i<len;i++){                    /*写成了26,找了好久*/        index=str[i]-'a';        while(p->next[index]==NULL&&p!=root)   /*预测一下,下面没有了就赶紧跳到fail去。(root跳个屁啊)*/             p=p->fail;        p=p->next[index];        if(p==NULL)            p=root;        trie temp=p;        while(temp!=root&&temp->count!=-1){     /*通过fail指针看一下到目前为止的后缀串有没有单词*/            result+=temp->count;            temp->count=-1;            temp=temp->fail;        }    }    return result;}int main(){    int ncase,n;    scanf("%d",&ncase);    while(ncase--){        head=tail=0;        creat(root);        scanf("%d",&n);        for(int i=0;i<n;i++){            scanf("%s",keyword);            insert(root,keyword);        }        build_ac();        scanf("%s",str);        printf("%d\n",query(root));    }    return 0;}


原创粉丝点击