【题解】CF1320D Reachable Strings

CF1320D Reachable Strings

\(\text{Solution:}\)

先来发现操作的性质,发现其本质是一个对 \(0\) 进行的位移,而且位移前后 \(0\) 位置的奇偶性不变。

那么,我们发现,如果一个子串能变成另外一个,当且仅当其 \(0\) 组成的部位构造相同、奇偶性相同。

所以这也就启发我们直接对 \(0\) 的位置进行哈希。所以考虑直接在原串上,只对 \(0\) 的位置以奇偶性为值来哈希。

判断的时候对开头的奇偶性分一下类即可。

注意哈希的写法要规范:以后就用倒着的。

for(){
  hash[i]=hash[i-1]*base+v[i]
}
query(){return (hash[r]-hash[l-1]*pw[r-l+1]);}

代码:

#include<bits/stdc++.h>
using namespace std;
const int N=2e5+10;
const int hmod=1004535809;
const int base=23;
int h[N][2],a[N],n,m,c[N];
int pw[N],inv[N],cnt[N];
char s[N];
inline int Add(int x,int y,int M=hmod){return (x+y)%M;}
inline int Mul(int x,int y,int M=hmod){return 1ll*x*y%M;}
inline int Dec(int x,int y,int M=hmod){return (x-y+M)%M;}
inline int qpow(int x,int y,int M=hmod){
	int res=1;
	while(y){
		if(y&1)res=Mul(res,x,M);
		x=Mul(x,x,M);y>>=1;
	}
	return res;
}
inline int read(){
	int s=0,w=1;
	char ch=getchar();
	while(!isdigit(ch)){
		if(ch=='-')w=-1;
		ch=getchar();
	}
	while(isdigit(ch)){
		s=s*10+ch-'0';
		ch=getchar();
	}
	return s*w;
}
int query(int l,int r){
	int opt=l&1;
	int R=Dec(h[r][opt],Mul(h[l-1][opt],pw[cnt[r]-cnt[l-1]]));
	return R;
}
int main(){
	freopen("in.txt","r",stdin);
	n=read();
	scanf("%s",s+1);
	for(int i=1;i<=n;++i)a[i]=s[i]-'0';
	pw[0]=1;
	for(int i=1;i<=n+1;++i)pw[i]=Mul(pw[i-1],base);
	inv[n+1]=qpow(pw[n+1],hmod-2);
	for(int i=n+1;i;--i)inv[i-1]=Mul(inv[i],base);
	h[0][0]=h[0][1]=1;
	for(int i=1;i<=n;++i){
		cnt[i]=cnt[i-1]+(a[i]==0);
		if(a[i]==1){
			h[i][0]=h[i-1][0];
			h[i][1]=h[i-1][1];
			continue;
		}
		cnt[i]=cnt[i-1]+1;
		int v=i&1;
		h[i][0]=Add(Mul(h[i-1][0],base),v+1);
		h[i][1]=Add(Mul(h[i-1][1],base),(v^1)+1);
	}
	m=read();
	while(m--){
		int l=read(),r=read(),len=read();
		if(query(l,l+len-1)==query(r,r+len-1))puts("Yes");
		else puts("No");
	}
	return 0;
}
posted @ 2021-10-04 21:19  Refined_heart  阅读(23)  评论(0编辑  收藏  举报