hdu3065 病毒侵袭持续中(AC自动机)

来源:互联网 发布:系统性能优化 编辑:程序博客网 时间:2024/06/05 05:00

题目点我点我点我

题意:给你一些字符串,再给你一个长字符串,问之前的那些字符串分别出现过几次,按输入的顺序输出字符串和其出现次数。
跟上题有一点点变化,主要是主串有可能有不是字母,查询时注意一下就可以了。
另开一个数组作为记录每个模式串的次数。

#include <iostream>#include <stdio.h>#include <stdlib.h>#include <string.h>#include <math.h>#include <algorithm>#include <malloc.h>#include <queue>using namespace std;int num[1050];struct Trie{    Trie *fail,*next[26];    int last;    Trie()    {        for(int i=0;i<26;i++)            next[i]=NULL;        fail=NULL;        last=-1;    }}*root;void inserttrie(char *str,int k){    int len=strlen(str);    Trie *p=root;    for(int i=0;i<len;i++)    {        int id=str[i]-'A';        if(p->next[id]==NULL)        {            p->next[id]=new Trie;        }        p=p->next[id];    }    p->last=k;}void buildfail(){    Trie *son,*temp,*p=root;    queue<struct Trie*>que;    que.push(p);    while(!que.empty())    {        temp=que.front();        que.pop();        for(int i=0;i<26;i++)        {            son=temp->next[i];            if(son!=NULL)            {                if(temp==root)son->fail=root;                else                {                    p=temp->fail;                    while(p)                    {                        if(p->next[i])                        {                            son->fail=p->next[i];                            break;                        }                        p=p->fail;                    }                    if(!p)son->fail=root;                }                que.push(son);            }        }    }}void querry(char *str){    int len=strlen(str);    Trie *p=root;    Trie *temp;    for(int i=0;i<len;i++)    {        if(str[i]>='A'&&str[i]<='Z')        {            int id=str[i]-'A';            while(p!=root&&p->next[id]==NULL)p=p->fail;            p=p->next[id];            if(!p)p=root;            temp=p;            while(temp!=root)            {                if(temp->last>=0)                {                    num[temp->last]++;                }                temp=temp->fail;            }        }        else   /*不是大写字母的就回到根节点重新开始*/        {            p=root;            continue;        }    }}int main(){    int n;    char str[1050][55];    char web[2000100];    while(~scanf("%d",&n))    {        memset(num,0,sizeof(num));        root=new Trie;        for(int i=1;i<=n;i++)        {            scanf("%s",str[i]);            inserttrie(str[i],i);        }        buildfail();        scanf("%s",web);        querry(web);        for(int i=1;i<=n;i++)        {            if(num[i]>0)            {                printf("%s: %d\n",str[i],num[i]);            }        }    }    return 0;}
0 0
原创粉丝点击