HDU2222 Keywords Search

来源:互联网 发布:神之浩劫等待游戏数据 编辑:程序博客网 时间:2024/06/05 06:39

题意:给你n个字符串以及一个字符串text,求这n个字符串中有几个在text中出现过。


这是一个典型的多串匹配问题,直接使用AC自动机的模板就行。

但这个题有点值得注意的地方,就是它的数据特别大,所以在输入时使用cin会超时,我就在这里WA了20多次。

#include <iostream>#include <string>#include <cstring>#include <queue>#include <cstdio>using namespace std;#define MAXN 285010char s[1000010];struct Trie{    int next[26];    int count;    //int cur;    int fail;}tr[MAXN];int k;//string s;void CreateTrie() //建立Trie{    unsigned cur=0,i,l=strlen(s);    for(i=0;i<l;i++)    {        int id=s[i]-'a';        if(tr[cur].next[id]==-1)        {            tr[k].count=0;            tr[k].fail=-1;            for(int j=0;j<26;j++) tr[k].next[j]=-1;            tr[cur].next[id]=k++;        }        cur=tr[cur].next[id];    }    tr[cur].count++;}* 结点的失败指针所指向结点的特征: * 被指向的结点至根节点的字符串必须 * 与以该结点为后缀的字符串相等,即后缀==前缀 *void BuildFail() //用BFS建立fail指针{    int cur=0,temp;    queue<int> Q;    Q.push(cur);    while(!Q.empty())    {        cur=Q.front();        Q.pop();        for(int i=0;i<26;i++)        {            int x=tr[cur].next[i];            if(x==-1) continue;            //第一个元素的fail一定是指向根节点            if(0==cur) tr[x].fail=0;            else            {                temp=tr[cur].fail; //失败指针                while(temp!=-1)  //匹配为空或找到匹配                {                    if(tr[temp].next[i]!=-1)                    {                        tr[x].fail=tr[temp].next[i];                        break;                    }                    temp=tr[temp].fail;                }                if(temp==-1) tr[x].fail=0;//为空则从头匹配            }            Q.push(x);        }    }}int Search(){    int i,ans=0,cur=0,l=strlen(s);    for(i=0;i<l;i++)    {        int id=s[i]-'a';        while(tr[cur].next[id]==-1&&cur!=0) cur=tr[cur].fail;        cur=tr[cur].next[id];        if(cur==-1) cur=0;        int temp=cur;        while(temp!=0&&tr[temp].count!=-1)        {//求的是多少个关键字被匹配,因此每个关键字最多被匹配一次            ans+=tr[temp].count;            tr[temp].count=-1;            temp=tr[temp].fail;        }    }    return ans;}int main(){    //cout<<sizeof(tr)/1000<<endl;    int t,n;    cin>>t;    while(t--)    {        cin>>n;        //getchar();        //memset(tr,0,sizeof(tr));        //Init(n);        tr[0].fail=-1;        tr[0].count=0;        for(int i=0;i<26;i++) tr[0].next[i]=-1;        k=1;        for(int i=0;i<n;i++)        {            //cin>>s;            //gets(s);            scanf("%s",s);            CreateTrie();        }        BuildFail();        //cin>>s;        scanf("%s",s);//这里使用cin作为输入会超时。        //cout<<s<<endl;        cout<<Search()<<endl;    }    return 0;}



0 0
原创粉丝点击