您的位置:首页 > 其它

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

2017-02-08 22:20 369 查看
题意:给一串字符串再给一个字符串,求前面那些串有多少出现在这个串中。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;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  AC自动机