裸的ac自动机居然没有看出来。。。
于是乎手撕了一发,
话说果然还是不喜欢用模板,
这篇挂出来就当是以后自己ac自动机的写法了。
挺好看的。。。
#include<iostream>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<cstdlib>
#include<algorithm>
using namespace std;
char s[200100],w_s[200100],tmp_s[200100];
int q[200100],q_tail,q_head,s_tail,s_len[200100],tot;
struct rec
{
int next[30];
int fail,count;
}tree[100100];
void clear(int x)
{
for (int i=1;i<=27;i++)
tree[x].next[i]=-1;
tree[x].count=0;
tree[x].fail=0;
}
void insert(char a[])
{
int len=strlen(a);
int i,j,now=0,tmp;
for (int i=0;i<len;i++)
{
tmp=a[i]-'a'+1;
if (tree[now].next[tmp]==-1)
{
tree[now].next[tmp]=++tot;
clear(tot);
}
now=tree[now].next[tmp];
}
tree[now].count++;
}
void makefail()
{
int now,now_f;
q_tail=q_head=0;
for (int i=1;i<=26;i++)
if (tree[0].next[i]!=-1)
{
q[++q_tail]=tree[0].next[i];
}
while (q_tail!=q_head)
{
q_head++;
now=q[q_head];
for (int i=1;i<=26;i++)
{
if (tree[now].next[i]!=-1)
{
q_tail++;
q[q_tail]=tree[now].next[i];
now_f=tree[now].fail;
while (now_f>0&&tree[now_f].next[i]==-1)
now_f=tree[now_f].fail;
if (tree[now_f].next[i]!=-1)
now_f=tree[now_f].next[i];
tree[tree[now].next[i]].fail=now_f;
}
}
}
}
void ac_work(char a[],int len)
{
int tmp=0,ans=0,p;
for (int i=1;i<=len;i++)
{
int now=a[i]-'a'+1;
while (tmp>0&&tree[tmp].next[now]==-1) tmp=tree[tmp].fail;
if (tree[tmp].next[now]!=-1)
{
tmp=tree[tmp].next[now];
p=tmp;
while (p>0)
{
ans+=tree[p].count;
p=tree[p].fail;
}
}
}
printf("%d\n",ans);
}
int main()
{
freopen("test.in","r",stdin);
freopen("test.out","w",stdout);
int t,n,m;
scanf("%d",&t);
s_tail=0;
while (t--)
{
tot=0;
clear(0);
s_tail=0;
scanf("%d%d",&n,&m);
for (int i=1;i<=n;i++)
{
scanf("%s",tmp_s);
int tmp_len=strlen(tmp_s);
s_len[i]=tmp_len;
for (int j=1;j<=tmp_len;j++)
s[s_tail+j]=tmp_s[j-1];
s_tail+=tmp_len;
}
for (int i=1;i<=m;i++)
{
scanf("%s",tmp_s);
insert(tmp_s);
}
makefail();
s_tail=1;
for (int i=1;i<=n;i++)
{
for (int j=s_tail;j<=s_tail+s_len[i]-1;j++)
w_s[j-s_tail+1]=s[j];
s_tail+=s_len[i];
ac_work(w_s,s_len[i]);
}
}
return 0;
}