Description
在美麗的玄武湖畔,雞鳴寺邊,雞籠山前,有一塊富饒而秀美的土地,人們喚作進香河。相傳一日,一縷紫氣從天而至,只一瞬間便消失在了進香河中。老人們說,這是玄武神靈將天書藏匿在此。
很多年後,人們終於在進香河地區發現了帶有玄武密碼的文字。更加神奇的是,這份帶有玄武密碼的文字,與玄武湖南岸臺城的結構有微妙的關聯。於是,漫長的破譯工作開始了。
經過分析,我們可以用東南西北四個方向來描述臺城城磚的擺放,不妨用一個長度爲N的序列來描述,序列中的元素分別是‘E’,‘S’,‘W’,‘N’,代表了東南西北四向,我們稱之爲母串。而神祕的玄武密碼是由四象的圖案描述而成的M段文字。這裏的四象,分別是東之青龍,西之白虎,南之朱雀,北之玄武,對東南西北四向相對應。
現在,考古工作者遇到了一個難題。對於每一段文字,其前綴在母串上的最大匹配長度是多少呢?
Input
第一行有兩個整數,N和M,分別表示母串的長度和文字段的個數。
第二行是一個長度爲N的字符串,所有字符都滿足是E,S,W和N中的一個。
之後M行,每行有一個字符串,描述了一段帶有玄武密碼的文字。依然滿足,所有字符都滿足是E,S,W和N中的一個。
Output
輸出有M行,對應M段文字。
每一行輸出一個數,表示這一段文字的前綴與母串的最大匹配串長度。
Sample Input
7 3
SNNSSNS
NNSS
NNN
WSEE
Sample Output
4
2
0
HINT
對於100%的數據,N<=10^7,M<=10^5,每一段文字的長度<=100。
應上傳者要求,此題不公開,如有異議,請提出.
SAM模板題。
注意開兩倍空間。
#include <bits/stdc++.h>
#define N 10000010
#define M 110
using namespace std;
int n,m,to[M];
char s[N],z[M];
struct node{
node *ch[4],*fail;
int dep;
}t[N<<1],*root=t,*tail=t;
node *newnode(){
(++tail)->fail=t;
tail->ch[0]=tail->ch[1]=tail->ch[2]=tail->ch[3]=t;
return tail;
}
node* add(node *p,int c){
node *cur=newnode(),*q=t,*f;
cur->dep=p->dep+1;
for (node *i=p;i!=t;i=i->fail){
if (i->ch[c]!=t){
f=i; q=i->ch[c];
break;
}
i->ch[c]=cur;
}
if (q==t){
cur->fail=root;
return cur;
}
if (q->dep==f->dep+1)
cur->fail=q;
else{
node *nq=newnode();
nq->dep=f->dep+1;
nq->fail=q->fail;
cur->fail=q->fail=nq;
for (node *i=f;i!=t && i->ch[c]==q;i=i->fail)
i->ch[c]=nq;
for (int i=0;i<4;i++)
nq->ch[i]=q->ch[i];
}
return cur;
}
void build(){
(root=newnode())->dep=0;
to['E']=0,to['S']=1,to['W']=2,to['N']=3;
node *las=root;
for (int i=0;i<n;i++)
las=add(las,to[s[i]]);
}
int main(){
scanf("%d%d",&n,&m);
scanf(" %s",s);
build();
int len,ans; node *cur;
for (int i=1;i<=m;i++){
scanf(" %s",z);
ans=0,len=strlen(z);
cur=root;
for (int j=0;j<len;ans++,j++){
cur=cur->ch[to[z[j]]];
if (cur==t) break;
}
printf("%d\n",ans);
}
return 0;
}