对于询问串建AC自动机,用母串匹配,标记访问过的节点不再被访问,最后枚举每个串统计答案
#include<cstdio>
#include<cstring>
using namespace std;
int cnt,tree[10000005][5],a[10000005],len[100005],Fail[10000005],vis[10000005],q[10000005];
char s[10000005],S[100005][105];
void update(int x){
for (int i=0; i<4; i++)
if (!tree[x][i]) tree[x][i]=tree[Fail[x]][i];
}
void ac_(){
int head=0,tail=0;
vis[0]=1;
for (int i=0; i<4; i++)
if (tree[0][i]){
update(tree[0][i]);
q[++tail]=tree[0][i];
vis[tree[0][i]]=1;
}
while (head<tail){
int x=q[++head];
for (int i=0; i<4; i++){
int V=tree[x][i];
if (vis[V]) continue;
Fail[V]=tree[Fail[x]][i];
update(V);
vis[V]=1;
q[++tail]=V;
}
}
}
int main(){
int n,m;
scanf("%d%d",&n,&m);
scanf("%s",s+1);
for (int i=1; i<=n; i++){
if (s[i]=='E') a[i]=0;
else if (s[i]=='S') a[i]=1;
else if (s[i]=='W') a[i]=2;
else a[i]=3;
}
for (int i=1; i<=m; i++){
scanf("%s",S[i]+1);
len[i]=strlen(S[i]+1);
int now=0;
for (int j=1; j<=len[i]; j++){
int x;
if (S[i][j]=='E') x=0;
else if (S[i][j]=='S') x=1;
else if (S[i][j]=='W') x=2;
else x=3;
if (!tree[now][x]) tree[now][x]=++cnt;
now=tree[now][x];
}
// sz[now]=1;
}
ac_();
// printf("%d
",tree[1][3]);
memset(vis,0,sizeof(vis));
int now=0;
for (int i=1; i<=n; i++){
now=tree[now][a[i]];
// printf("%d ",now);
if (!vis[now]){
int Pre=now;
vis[Pre]=1;
Pre=Fail[Pre];
while (!vis[Pre]){
vis[Pre]=1;
Pre=Fail[Pre];
}
}
}
// printf("
");
for (int i=1; i<=m; i++){
int now=0,maxlen=0;
for (int j=1; j<=len[i]; j++){
int x;
if (S[i][j]=='E') x=0;
else if (S[i][j]=='S') x=1;
else if (S[i][j]=='W') x=2;
else x=3;
now=tree[now][x];
if (!vis[now]) break;
maxlen=j;
}
printf("%d
",maxlen);
}
return 0;
}