hdu_2222_Keywords Search(AC自动机)

来源:互联网 发布:mac safari 插件管理 编辑:程序博客网 时间:2024/05/16 07:03

题型:AC自动机


题意:给出一系列模式串,问在主串中这些模式串总共出现了多少次。


分析:

     看到题目就能想到的解决办法就是KMP,但是这是行不通的,因为有很多个模式串,一个一个的来KMP求解会TLE。介个时候AC自动机就登场了~

     AC自动机是一种多模匹配算法,要搞懂这个算法,需要先了解字典树、KMP等算法知识。

     AC自动机的原理很简单,先用给出的多个模式串构建字典树,然后对字典树做KMP得到失败指针数组fail[],然后进行匹配得到答案。


代码:

#include<iostream>#include<cstdio>#include<cmath>#include<cstring>using namespace std;const int kind=26;struct node{    node *fail;    node *next[kind];    int count;    node(){        fail=NULL;        count=0;        memset(next,NULL,sizeof(next));    }}*q[500001];char keyword[51];char str[1000001];int head,tail;//构造tire treevoid insert(char *str,node *root){    node *p=root;    int i=0,index;    while(str[i]){        index=str[i]-'a';        if(p->next[index]==NULL) p->next[index]=new node();        p=p->next[index];        i++;    }    p->count++;}//构造失败指针void build_ac_automation(node *root){    int i;    root->fail=NULL;    q[head++]=root;    while(head!=tail){        node *temp=q[tail++];        node *p=NULL;        for(i=0;i<26;i++){            if(temp->next[i]!=NULL){                if(temp==root) temp->next[i]->fail=root;                else{                    p=temp->fail;                    while(p!=NULL){                        if(p->next[i]!=NULL){                            temp->next[i]->fail=p->next[i];                            break;                        }                        p=p->fail;                    }                    if(p==NULL) temp->next[i]->fail=root;                }                q[head++]=temp->next[i];            }        }    }}//查询int query(node *root){    int i=0,cnt=0,index,len=strlen(str);    node *p=root;    while(str[i]){        index=str[i]-'a';        while(p->next[index]==NULL&&p!=root) p=p->fail;        p=p->next[index];        p=(p==NULL)?root:p;        node *temp=p;        while(temp!=root&&temp->count!=-1){            cnt+=temp->count;            temp->count=-1;            temp=temp->fail;        }        i++;    }    return cnt;}int main(){    int t,n;    scanf("%d",&t);    while(t--){        scanf("%d",&n);        getchar();        head=tail=0;        node *root=new node();        while(n--){            gets(keyword);            insert(keyword,root);        }        build_ac_automation(root);        scanf("%s",str);        printf("%d\n",query(root));    }    return 0;}


原创粉丝点击