[BZOJ4327] JSOI2012玄武密码
2017-12-14 10:15
471 查看
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模板题。
注意开两倍空间。
在美丽的玄武湖畔,鸡鸣寺边,鸡笼山前,有一块富饶而秀美的土地,人们唤作进香河。相传一日,一缕紫气从天而至,只一瞬间便消失在了进香河中。老人们说,这是玄武神灵将天书藏匿在此。
很多年后,人们终于在进香河地区发现了带有玄武密码的文字。更加神奇的是,这份带有玄武密码的文字,与玄武湖南岸台城的结构有微妙的关联。于是,漫长的破译工作开始了。
经过分析,我们可以用东南西北四个方向来描述台城城砖的摆放,不妨用一个长度为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 ,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->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; }
相关文章推荐
- BZOJ4327 : JSOI2012 玄武密码
- [BZOJ4327]-[JSOI2012]玄武密码-AC自动机
- BZOJ 4327: JSOI2012 玄武密码
- [BZOJ]4327 [JSOI2012] 玄武密码 AC自动机
- 【JSOI2012】【BZOJ4327】玄武密码
- 【BZOJ4327】【JSOI2012】玄武密码
- BZOJ-4327:JSOI2012 玄武密码(AC自动机模板题)
- BZOJ_4327_JSOI2012 玄武密码_AC自动机
- BZOJ 4327 JSOI2012 玄武密码(后缀自动机)
- 【BZOJ4327】JSOI2012 玄武密码 AC自动机
- 【bzoj4327】【JSOI2012】【玄武密码】【AC自动机】
- BZOJ[4327]JSOI2012 玄武密码 AC自动机
- bzoj 4327: JSOI2012 玄武密码 (AC自动机)
- BZOJ 4327 【JSOI 2012】 玄武密码 AC自动机+dfs
- [BZOJ4327]JSOI2012 玄武密码(AC自动机)
- 4327: JSOI2012 玄武密码[SAM]
- 【bzoj4327】JSOI2012 玄武密码 AC自动机
- BZOJ 4327: JSOI2012 玄武密码
- BZOJ4327 JSOI2012玄武密码(AC自动机)
- 玄武密码(bzoj4327)(JSOI2012)