题目思路
如题目所示,就是二分求第一个不同的点,然后判断后面的字符串是否相同即可
代码
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
typedef pair<int,int> pii;
#define fi first
#define se second
#define debug printf("aaaaaaaaaaa\n");
const int maxn=1e5+5,inf=0x3f3f3f3f,mod=1e9+7;
const ll INF=0x3f3f3f3f3f3f3f3f;
ull tree[maxn<<2],base=233;
ull pre[maxn];
int n,m;
char s[maxn];
void pushup(int node,int l,int r){
int mid=(l+r)/2;
// [mid+1,r]
tree[node]=tree[node<<1]*pre[r-mid]+tree[node<<1|1];
}
void build(int node,int l,int r){
if(l==r){
tree[node]=s[l];
return ;
}
int mid=(l+r)/2;
build(node<<1,l,mid);
build(node<<1|1,mid+1,r);
pushup(node,l,r);
}
void update(int node,int pos,int val,int l,int r){
if(l==r){
tree[node]=val;
return ;
}
int mid=(l+r)/2;
if(mid>=pos) update(node<<1,pos,val,l,mid);
else update(node<<1|1,pos,val,mid+1,r);
pushup(node,l,r);
}
ull query(int node,int L,int R,int l,int r){
if(L<=l&&r<=R){
return tree[node];
}
int mid=(l+r)/2;
ull ans=0;
if(mid>=L) ans+= pre[max(0,min(R , r)- mid)]*query(node<<1,L,R,l,mid);
if(mid<R) ans+=query(node<<1|1,L,R,mid+1,r);
return ans;
}
int main(){
pre[0]=1;
for(int i=1;i<=1e5;i++){
pre[i]=pre[i-1]*base;
}
scanf("%d%d %s",&n,&m,s+1);
build(1,1,n);
for(int i=1;i<=m;i++){
int opt,x,l1,r1,l2,r2,flag;
char y;
scanf("%d",&opt);
if(opt==1){
scanf("%d %c",&x,&y);
update(1,x,y,1,n);
}else{
scanf("%d%d%d%d",&l1,&r1,&l2,&r2);
if(r1-l1!=r2-l2){
flag=0;
}else{
int len=r1-l1+1;
int l=1,r=len,ans=0;
while(l<=r){
int mid=(l+r)/2;
ull temp1=query(1,l1,l1+mid-1,1,n);
ull temp2=query(1,l2,l2+mid-1,1,n);
if(temp1==temp2){
ans=mid;
l=mid+1;
}else{
r=mid-1;
}
}
if(ans==len||ans==len-1){
flag=1;
}else{
ull temp1=query(1,l1+ans+1,r1,1,n);
ull temp2=query(1,l2+ans+1,r2,1,n);
flag=(temp1==temp2);
}
}
printf(flag?"YES\n":"NO\n");
}
}
return 0;
}