在美丽的玄武湖畔,鸡鸣寺边,鸡笼山前,有一块富饶而秀美的土地,人们唤作进香河。相传一日,一缕紫气从天而至,只一瞬间便消失在了进香河中。老人们说,这是玄武神灵将天书藏匿在此。
很多年后,人们终于在进香河地区发现了带有玄武密码的文字。更加神奇的是,这份带有玄武密码的文字,与玄武湖南岸台城的结构有微妙的关联。于是,漫长的破译工作开始了。
经过分析,我们可以用东南西北四个方向来描述台城城砖的摆放,不妨用一个长度为N的序列来描述,序列中的元素分别是‘E’,‘S’,‘W’,‘N’,代表了东南西北四向,我们称之为母串。而神秘的玄武密码是由四象的图案描述而成的M段文字。这里的四象,分别是东之青龙,西之白虎,南之朱雀,北之玄武,对东南西北四向相对应。
现在,考古工作者遇到了一个难题。对于每一段文字,其前缀在母串上的最大匹配长度是多少呢?
第一行有两个整数,N和M,分别表示母串的长度和文字段的个数。
第二行是一个长度为N的字符串,所有字符都满足是E,S,W和N中的一个。
之后M行,每行有一个字符串,描述了一段带有玄武密码的文字。依然满足,所有字符都满足是E,S,W和N中的一个。
输出有M行,对应M段文字。
每一行输出一个数,表示这一段文字的前缀与母串的最大匹配串长度。
应上传者要求,此题不公开,如有异议,请提出.
#include <iostream>
#include <cstdio>
#include <queue>
#include <cstring>
#include <algorithm>
using namespace std;
#define reg register
inline int read() {
int res=0;char ch=getchar();
while(!isdigit(ch)) ch=getchar();
while(isdigit(ch))res=(res<<3)+(res<<1)+(ch^48),ch=getchar();
return res;
}
#define N 10000005
int n, m;
int nxt[N][5], fail[N], cnt;
int mark[N];
char str[N], stt[100005][105], len[100005];
int end[100005], fa[N];
inline int id(char c)
{
if (c == ‘N‘) return 1;
if (c == ‘S‘) return 3;
if (c == ‘W‘) return 2;
return 4;
}
inline void ins(int i)
{
len[i] = strlen(stt[i] + 1);
int p = 1;
int now = 0;
while(p <= len[i])
{
if (!nxt[now][id(stt[i][p])]) nxt[now][id(stt[i][p])] = ++cnt, fa[cnt] = now;
now = nxt[now][id(stt[i][p])];
p++;
}
end[i] = now;
}
inline void AC_Match()
{
queue <int> q;
fail[0] = -1;
for (reg int i = 1 ; i <= 4 ; i ++) if (nxt[0][i]) q.push(nxt[0][i]), fail[nxt[0][i]] = 0;
while(!q.empty())
{
int x = q.front();
q.pop();
for (reg int i = 1 ; i <= 4 ; i ++)
{
if (nxt[x][i]) fail[nxt[x][i]] = nxt[fail[x]][i], q.push(nxt[x][i]);
else nxt[x][i] = nxt[fail[x]][i];
}
}
}
inline void AC_Auto()
{
int p = 1, now = 0;
while(p <= n)
{
now = nxt[now][id(str[p])];
int x = now;
while(~x)
{
if (mark[x]) break;
mark[x] = 1;
x = fail[x];
}
p++;
}
}
inline int solve(int x)
{
int y = len[x];
int now = end[x];
while(now)
{
if (mark[now]) return y;
y--;
now = fa[now];
}
return 0;
}
int main()
{
n = read(), m = read();
scanf("%s", str + 1);
for (reg int i = 1 ; i <= m ; i ++)
{
scanf("%s", stt[i] + 1);
ins(i);
}
AC_Match();
AC_Auto();
for (reg int i = 1 ; i <= m ; i ++) printf("%d\n", solve(i));
return 0;
}