hdu 2222 AC自动机模板(非指针)

来源:互联网 发布:李世默 知乎 编辑:程序博客网 时间:2024/06/05 10:34

题意:给一串字符串再给一个字符串,求前面那些串有多少出现在这个串中。n<=10000,sumlen<=1000000.
PS:好久没打AC自动机了,打一发模板练练手,不过相当讨厌c艹的指针,看着就恶心。。
代码:

#include<iostream>#include<cstdio>#include<cmath>#include<queue>#include<algorithm>#include<cstring>#define fo(i,a,b) for(int i=a;i<=b;i++)using namespace std;const int maxn=5e5+5;int n,len,trie[maxn][26],fail[maxn],out[maxn],tot,cnt;char ch[60],s[1000005];queue <int>q;void insert(int x,int y){    if(y==len)    {        out[x]++;        return;    }    int w=ch[y]-'a';    if (!trie[x][w])trie[x][w]=++cnt;    insert(trie[x][w],y+1);}void getfail(){    fo(i,0,25)if (trie[0][i])q.push(trie[0][i]);    while (!q.empty())    {        int r=q.front();        q.pop();        fo(i,0,25)        if (trie[r][i])        {            int u=trie[r][i],v=fail[r];            q.push(u);            while (v&&!trie[v][i])v=fail[v];            fail[u]=trie[v][i];        }    }}inline int query(){    int p=0,ans=0;    fo(i,0,len-1)    {        int w=s[i]-'a';        while (p&&!trie[p][w])p=fail[p];        p=trie[p][w];        int o=p;        while (o)        {            if (!out[o])break;            ans+=out[o];            out[o]=0;            o=fail[o];        }    }    return ans;}int main(){    int t;    scanf("%d",&t);    while (t--)    {        scanf("%d",&n);        memset(fail,0,sizeof(fail));        memset(trie,0,sizeof(trie));        memset(out,0,sizeof(out));        tot=0;        fo(i,1,n)        {            scanf("%s",ch);            len=strlen(ch);            insert(0,0);        }        getfail();        scanf("%s",s);        len=strlen(s);        printf("%d\n",query());    }    return 0;}
0 0