HDU 3065 病毒侵袭持续中 AC自动机

来源:互联网 发布:基础编程书 编辑:程序博客网 时间:2024/05/19 14:52
#include<iostream>#include<cstdio>#include<cstring>#include<queue>#include<set>using namespace std;char key[1010][52],s[2000010];int ans[1010],n;struct ACautomata{    int next[50010][26],fail[50010],idx[50010],last[50010],num,root;    int newnode()    {        memset(next[num],0,sizeof next[num]);        idx[num]=0;        return num++;    }    void init()    {        num=0;        root=newnode();    }    void insert(char *s,int t)    {        int len=strlen(s),cur=root;        for(int i=0;i<len;++i)        {            int &tmp=next[cur][s[i]-'A'];            if(!tmp)tmp=newnode();            cur=tmp;        }        idx[cur]=t;    }    void getfail()    {        queue<int>q;        fail[root]=root;        for(int i=0;i<26;++i)        {            int u=next[root][i];            if(u)            {                fail[u]=last[u]=0;                q.push(u);            }        }        while(!q.empty())        {            int cur=q.front();            q.pop();            for(int i=0;i<26;++i)            {                int u=next[cur][i];                if(u)                {                    fail[u]=next[fail[cur]][i];                    last[u]=idx[fail[u]]?fail[u]:last[fail[u]];                    q.push(u);                }                else next[cur][i]=next[fail[cur]][i];            }        }    }    void query(char *s)    {        int len=strlen(s),cur=root;        for(int i=0;i<len;++i)        {            if(s[i]<'A'||s[i]>'Z'){cur=root;continue;}            cur=next[cur][s[i]-'A'];            int tmp=cur;            while(tmp!=root)            {                ++ans[idx[tmp]];                tmp=last[tmp];            }        }    }}ac;int main(){    while(~scanf("%d",&n))    {        ac.init();        memset(ans,0,sizeof ans);        memset(key,0,sizeof key);        memset(s,0,sizeof s);        for(int i=1;i<=n;++i)        {            scanf("%s",key[i]);            ac.insert(key[i],i);        }        scanf("%s",s);        ac.getfail();        ac.query(s);        for(int i=1;i<=n;++i)            if(ans[i])printf("%s: %d\n",key[i],ans[i]);    }}

这题就是保存一个匹配串的下标,然后更新答案通过下标,++ans[下标]。
还是错了几次,第一次是字符串大小开小了。第二次是原串中没有一个可以匹配的时候要continue,之前要把当前的节点返回到根。这个很显然但是我忘记了。

0 0
原创粉丝点击