列表

详情


NC50352. 玄武密码

描述

在美丽的玄武湖畔,鸡鸣寺边,鸡笼山前,有一块富饶而秀美的土地,人们唤作进香河。相传一日,一缕紫气从天而至,只一瞬间便消失在了进香河中。老人们说,这是玄武神灵将天书藏匿在此。
很多年后,人们终于在进香河地区发现了带有玄武密码的文字。更加神奇的是,这份带有玄武密码的文字,与玄武湖南岸台城的结构有微妙的关联。于是,漫长的破译工作开始了。
经过分析,我们可以用东南西北四个方向来描述台城城砖的摆放,不妨用一个长度为N的序列来描述,序列中的元素分别是E,S,W,N,代表了东南西北四向,我们称之为母串。而神秘的玄武密码是由四象的图案描述而成的M段文字。这里的四象,分别是东之青龙,西之白虎,南之朱雀,北之玄武,对东南西北四向相对应。
现在,考古工作者遇到了一个难题。对于每一段文字,其前缀在母串上的最大匹配长度是多少呢?

输入描述

第一行有两个整数,N和M,分别表示母串的长度和文字段的个数;
第二行是一个长度为N的字符串,所有字符都满足是E,S,W和N中的一个;
之后M行,每行有一个字符串,描述了一段带有玄武密码的文字。依然满足,所有字符都满足是E,S,W和N中的一个。

输出描述

输出有M行,对应M段文字。
每一行输出一个数,表示这一段文字的前缀与母串的最大匹配串长度。

示例1

输入:

7 3
SNNSSNS
NNSS
NNN
WSEE

输出:

4
2
0

原站题解

上次编辑到这里,代码来自缓存 点击恢复默认模板

C++(clang++11) 解法, 执行用时: 81ms, 内存消耗: 14316K, 提交时间: 2020-11-29 11:32:10

#include<bits/stdc++.h>
#define ep emplace
using namespace std;
const int mt=10201129;
bool rea[mt];
int n,m,u,v,i,j,tot=1,to;
int nxt[mt],ans[mt],a[mt][5];
string s,t[101129];
queue<int>q;
int dir(char ch){
	if(ch=='E')return 0;
	if(ch=='S')return 1;
	if(ch=='W')return 2;
	if(ch=='N')return 3;
	return 4;
}int main(){
	int len;
	a[0][0]=a[0][1]=a[0][2]=a[0][3]=1;
	q.push(1),scanf("%d%d",&n,&m),cin>>s;
	for(i=0;i<m;i++){
		cin>>t[i],len=t[i].length();
		for(u=1,j=0;j<len;j++){
			to=dir(t[i][j]);
			if(!a[u][to])a[u][to]=++tot;
			u=a[u][to];
		}
	}for(;!q.empty();q.pop()){
		u=q.front();
		for(i=0;i<4;i++)
			if(a[u][i])q.ep(a[u][i]),nxt[a[u][i]]=a[nxt[u]][i];
			else a[u][i]=a[nxt[u]][i];
	}for(u=1,i=0;i<n;i++){
		u=a[u][dir(s[i])];
		for(v=u;v&&!rea[v];v=nxt[v])
			rea[v]=true;
	}for(i=0;i<m;i++){
		len=t[i].length();
		for(u=1,j=0;j<=len;j++)
			if(!rea[u=a[u][dir(t[i][j])]]){
				printf("%d\n",j);
				break;
			}
	}return 0;
}

上一题