您的位置:首页 > 其它

ac自动机模板hdu2222

2017-08-05 10:00 337 查看
给你一堆字符串,和一个文本串,求有多少个字符串在文本串出现过

#include<cstdio>
#include<iostream>
#include<cstring>
#include<queue>
using namespace std;
const int maxn=550000;

struct AC_auto
{
int chd[maxn][26],v[maxn],f[maxn],last[maxn],sz,ans;
void init()
{
sz=1;ans=0;
memset(v,0,sizeof(v));
memset(f,0,sizeof(f));
memset(chd[0],0,sizeof(chd[0]));
}
void insert(char* p)
{
int cur=0;
for(;*p;p++)
{
if(!chd[cur][*p-'a'])
{
memset(chd[sz],0,sizeof(chd[sz]));
chd[cur][*p-'a']=sz++;
}
cur=chd[cur][*p-'a'];
}
v[cur]++;
}
bool query(char* p)
{
int cur=0;
for(;*p;p++)
{
if(!chd[cur][*p-'a']) break;
cur=chd[cur][*p-'a'];
}
return v[cur]&&(!(*p));
}
int getFail()
{
queue<int> q;
f[0]=0;
for(int c=0;c<26;c++)
{
int u=chd[0][c];
if(u)
{
f[u]=0; q.push(u); last[u]=0;
}
}
while(!q.empty())
{
int r=q.front(); q.pop();
for(int c=0;c<26;c++)
{
int u=chd[r][c];
if(!u){ chd[r][c]=chd[f[r]][c];continue;}///....
q.push(u);
int vv=f[r];
while(vv&&!chd[vv][c]) vv=f[vv];
f[u]=chd[vv][c];
last[u]=v[f[u]] ? f[u] : last[f[u]];
}
}
}
void solve(int j)
{
if(!j) return;
if(v[j])
{
ans+=v[j];
v[j]=0;
}
solve(last[j]);
}
void find(char* T)
{
int n=strlen(T),j=0;
getFail();
for(int i=0;i<n;i++)
{
j=chd[j][T[i]-'a'];
if(v[j]) solve(j);
else if(last[j]) solve(last[j]);
}
}
}ac;
int main(){
int T,n;
char s[1000005];
cin>>T;
while(T--)
{
scanf("%d",&n);
ac.init();
while(n--)
{
scanf("%s",s);
ac.insert(s);
}
scanf("%s",s);
ac.find(s);
printf("%d\n",ac.ans);
}
return 0;
}

hdu2222
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: