【Codeforces Round 336 (Div 2) E】【KMP 构造 脑洞 好题 模拟找规律】Marbles 两条路径同时出发前后行走能否恰好同时到终点

48 篇文章 0 订阅
24 篇文章 0 订阅

E. Marbles
time limit per test
2 seconds
memory limit per test
256 megabytes
input
standard input
output
standard output

In the spirit of the holidays, Saitama has given Genos two grid paths of length n (a weird gift even by Saitama's standards). A grid path is an ordered sequence of neighbouring squares in an infinite grid. Two squares are neighbouring if they share a side.

One example of a grid path is (0, 0) → (0, 1) → (0, 2) → (1, 2) → (1, 1) → (0, 1) → ( - 1, 1). Note that squares in this sequence might be repeated, i.e. path has self intersections.

Movement within a grid path is restricted to adjacent squares within the sequence. That is, from the i-th square, one can only move to the (i - 1)-th or (i + 1)-th squares of this path. Note that there is only a single valid move from the first and last squares of a grid path. Also note, that even if there is some j-th square of the path that coincides with the i-th square, only moves to (i - 1)-th and (i + 1)-th squares are available. For example, from the second square in the above sequence, one can only move to either the first or third squares.

To ensure that movement is not ambiguous, the two grid paths will not have an alternating sequence of three squares. For example, a contiguous subsequence (0, 0) → (0, 1) → (0, 0) cannot occur in a valid grid path.

One marble is placed on the first square of each grid path. Genos wants to get both marbles to the last square of each grid path. However, there is a catch. Whenever he moves one marble, the other marble will copy its movement if possible. For instance, if one marble moves east, then the other marble will try and move east as well. By try, we mean if moving east is a valid move, then the marble will move east.

Moving north increases the second coordinate by 1, while moving south decreases it by 1. Similarly, moving east increases first coordinate by 1, while moving west decreases it.

Given these two valid grid paths, Genos wants to know if it is possible to move both marbles to the ends of their respective paths. That is, if it is possible to move the marbles such that both marbles rest on the last square of their respective paths.

Input

The first line of the input contains a single integer n (2 ≤ n ≤ 1 000 000) — the length of the paths.

The second line of the input contains a string consisting of n - 1 characters (each of which is either 'N', 'E', 'S', or 'W') — the first grid path. The characters can be thought of as the sequence of moves needed to traverse the grid path. For example, the example path in the problem statement can be expressed by the string "NNESWW".

The third line of the input contains a string of n - 1 characters (each of which is either 'N', 'E', 'S', or 'W') — the second grid path.

Output

Print "YES" (without quotes) if it is possible for both marbles to be at the end position at the same time. Print "NO" (without quotes) otherwise. In both cases, the answer is case-insensitive.

Sample test(s)
input
7
NNESWW
SWSWSW
output
YES
input
3
NN
SS
output
NO
Note

In the first sample, the first grid path is the one described in the statement. Moreover, the following sequence of moves will get both marbles to the end: NNESWWSWSW.

In the second sample, no sequence of moves can get both marbles to the end.



#include<stdio.h>
#include<iostream>
#include<string.h>
#include<string>
#include<ctype.h>
#include<math.h>
#include<set>
#include<map>
#include<vector>
#include<queue>
#include<bitset>
#include<algorithm>
#include<time.h>
using namespace std;
void fre(){freopen("c://test//input.in","r",stdin);freopen("c://test//output.out","w",stdout);}
#define MS(x,y) memset(x,y,sizeof(x))
#define MC(x,y) memcpy(x,y,sizeof(x))
#define MP(x,y) make_pair(x,y)
#define ls o<<1
#define rs o<<1|1
typedef long long LL;
typedef unsigned long long UL;
typedef unsigned int UI;
template <class T1,class T2>inline void gmax(T1 &a,T2 b){if(b>a)a=b;}
template <class T1,class T2>inline void gmin(T1 &a,T2 b){if(b<a)a=b;}
const int N=1e6+10,M=0,Z=1e9+7,ms63=0x3f3f3f3f;
int casenum,casei;
int n;
char a[N],b[N];
int nxt[N];
void init()
{
	for(int i=1;i<=n;++i)
	{
		if(b[i]=='N')b[i]='S';
		else if(b[i]=='S')b[i]='N';
		else if(b[i]=='W')b[i]='E';
		else if(b[i]=='E')b[i]='W';
	}
	for(int i=1;i<=n/2;++i)swap(b[i],b[n+1-i]);
}
void getnxt()
{
	int j=0;nxt[1]=0;
	for(int i=2;i<=n;++i)
	{
		while(j&&b[j+1]!=b[i])j=nxt[j];
		if(b[j+1]==b[i])++j;
		nxt[i]=j;
	}
}
void kmp()
{
	int j=0;
	for(int i=1;i<=n;++i)
	{
		while(j&&b[j+1]!=a[i])j=nxt[j];
		if(b[j+1]==a[i])++j;
	}
	puts(j?"NO":"YES");
}
int main()
{
	while(~scanf("%d",&n))
	{
		--n;scanf("%s%s",a+1,b+1);
		init();
		getnxt();
		kmp();
	}
	return 0;
}
/*
【trick&&吐槽】
这题题意好难懂!

【题意】
给你两条长度同为n(2<=n<=1e6)的路径。
每条路径有行走规则,显然,在路径上的行走步数就会是n-1。

我们会接受到一个指令(这个指令由你给出)。
对于任意一条路径而言,一共有n个位置——
如果我们此刻是位于第i个位置,现在接受的这条指令的移动方向是dir,
而且如果路径上第i-1或者i+1位置(首先这个位置需要是存在的),是可以通过这个dir到达的,那么我们就会执行这条指令。

现在问你,是否存在一个指令,可以使得两条路径在指令结束的时候,都恰好达到最后的位置。
存在输出YES,不存在输出NO。

【类型】
脑洞 KMP

【分析】
这道题不光题意难懂,
懂了之后也感觉很鬼畜,而不知道怎么做。

然而这题,却是有结论的。
对于操作序列a,我们保持不变。
对于操作序列b,我们把所有的方向反过来,再把这个串的前后做对称颠倒操作。我们称这个操作为reverse操作,对应的串被叫做reverse串。
为什么我们想到reverse串呢?
因为这道题有一个很奇怪的限制,就是我们从一个位置,接受指令,可以走这个位置在定位上的前一个位置或者后一个位置。
也就是说,行走操作,对于一个串和其翻转串,是存在着对称性的。

基于之前找出的所有性质,我们可以从一些小数据模拟中找出问题的答案——
数据1:
2
S
N

对于这组数据,我们发现答案一定是NO。
因为,两个路径上的最后一步运动是反向的。
一个位点向下走了,对于另外一个位点,就会向上走。永远不会有两个位点同时走到终点的时刻。
其实问题可以扩大化,数据可以变成——
len
x...xS
x...xN
只是最后一步是恰好是反向的。同理,一样不可能使得两条路径同时到达终点。

那么,难道就是——
如果最后一步是恰好反向,那答案就是NO;否则答案就是YES?
不!
数据2:
...NW
...ES
最后一步并非反向,但是,最后两步是恰好对称反向。
也就是说,最后两步是形成恰好的反结构。我们发现答案也是NO。

我们由此延伸出一个判定。
如果a和b两个序列,可以从a中取出一个后缀,而在b中有同样长度的后缀,是恰好对称反向的,那么答案就是NO

为什么呢?
我们可以形成一个想象,拿出这两个路径最后反向对称的部分
把它们放在上下层,使它们在结构上形成覆盖关系。
于是,我们发现,如果两个序列都达到最后一个位置,必要条件是,两个路径序列需要形成交错。
首先,对于相邻位点(pos a pos b),显然因为所需指令不同,所以我们是不可能同时从pos a 到pos b,并从pos b 到pos a的。
那么,如果形成交错,我们一定要在这两个正反路径上,先到达一个相同的点。
肯定的是,这个相同的点,不会同时是两个路径的终点。

在这个时候,不论接下来的操作序列是什么,在两条路径上行走,都会存在同进同退的行走方案。
因而,我们不可能在这两个路径最后反向对称的部分,同时到达两个末端位置。于是,NO的结果是显然而且确定的。

====================================
于是,我们就可以说,这道题目输出NO的条件是——
当且仅当,在a串中存在某个后缀,与b串的翻转串中同长度后缀恰好匹配 吗?
如何证明呢?证明就要有证明充要性,即证明其充分性和必要性。
充分性我们已经证明了,即存在这样的对称结构,那么答案就是NO。

然而,我们还需要再考虑其必要性——
即证明,不存在反向对称后缀结构的话,对于两个路径的答案一定是YES么?
有一种走法。
我们先在路径1,通过最少步数走到末节点,然后如果路径2,没有走到末节点的话,
我们再在路径2,通过最少步数走到末节点。
以此循环,那么最后一定可以使得两个点都走到末点。
为什么呢?
因为我们在两条路径上,都有一个到末点的距离。分别设为disa和disb,总距离设为dis。
那么,我们可以说,按照前述的方案操作的话,总的dis一定是严格减少的。
为什么呢?
比如说我们现在a路径到末点了,b路径开始向其末点走,那么dis不减少的条件,显然是a路径与b路径最后部分恰好对称反向。
而这个结构已经证明不存在了,于是总的dis一定严格减少,答案一定是YES.

==================
于是这道题就做完啦.
我们可以通过
反向一个串,然后再把它做对称,得到的串作为模板串。
然后另外一个串做匹配串,做KMP。
如果不变换的那个串,最后一个位置是存在匹配长度的。
那么意思是,存在反向对称结构(为什么?可以围绕KMP体会一下)。答案就是NO
而最后一个位置的匹配长度是0的话,答案就是YES

==================
于是这道题就完全做完啦~

【时间复杂度&&优化】
O(n)

*/


  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值