【题解】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;
}