AC自动机模板
i的fail指针指向j说明j的后缀一定在i的后缀中出现,对于每个点若访问过,则标记为1,
那然后建一条从j指向i的边,当j的子树中有被访问过时j的值也赋值为1(说明这个前缀在i中出现过)
/**************************************************************
Problem: 4327
User: syh0313
Language: C++
Result: Accepted
Time:3792 ms
Memory:494064 kb
****************************************************************/
#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <string>
#include <cmath>
using
namespace
std;
const
int
maxn=10000100;
int
n,m,root=1,cnt=1,head,tail,q[10000010];
string s[maxn],mu,ss;
int
topt,to[maxn],st[maxn],nt[maxn];
struct
data
{
int
c[4],v,fa,id;
}a[10000010];
void
add(
int
x,
int
y)
{to[++topt]=y; nt[topt]=st[x]; st[x]=topt;}
int
ok(
char
c)
{
if
(c==
'E'
)
return
0;
if
(c==
'W'
)
return
1;
if
(c==
'S'
)
return
2;
if
(c==
'N'
)
return
3;
return
0;
}
void
insert(
int
num)
{
int
len=ss.length();
int
now=root;
for
(
int
i=0;i<len;i++)
{
int
x=ok(ss[i]);
if
(!a[now].c[x]) a[now].c[x]=++cnt;
now=a[now].c[x];
}
a[now].id=num;
}
void
getfail()
{
head=1; tail=1; q[1]=root;
while
(head<=tail)
{
int
now=q[head++];
for
(
int
i=0;i<=3;i++)
{
int
to=a[now].c[i];
if
(!to)
continue
;
if
(now==root) a[to].fa=root,add(root,to);
else
{
int
father=a[now].fa;
while
(father)
{
if
(a[father].c[i])
{a[to].fa=a[father].c[i]; add(a[to].fa,to);
break
;}
father=a[father].fa;
}
if
(!father) {a[to].fa=root; add(root,to);}
}
q[++tail]=to;
}
}
return
;
}
void
search()
{
int
len=mu.length();
int
now=root;
for
(
int
i=0;i<len;i++)
{
int
x=ok(mu[i]);
while
(!a[now].c[x] && now!=root) now=a[now].fa;
if
(now==root && !a[now].c[x])
continue
;
now=a[now].c[x];
a[now].v=1;
}
}
int
work(
int
x)
{
int
p=st[x];
while
(p)
{
if
(work(to[p])) a[x].v=1;
p=nt[p];
}
return
a[x].v;
}
int
find(string st)
{
int
len=st.length();
int
now=root;
int
ans=0;
for
(
int
i=0;i<len;i++)
{
int
x=ok(st[i]);
if
(a[a[now].c[x]].v==0)
break
;
ans++;
now=a[now].c[x];
}
return
ans;
}
int
main()
{
//freopen("1.in","r",stdin);
//freopen("my.out","w",stdout);
ios::sync_with_stdio(
false
);
cin>>n>>m>>mu;
for
(
int
i=1;i<=m;i++) {cin>>ss; insert(i); s[i]=ss;}
getfail();
search();
work(root);
for
(
int
i=1;i<=m;i++)
printf
(
"%d\n"
,find(s[i]));
return
0;
}