因为修改的次数比较少,所以每次暴力重构hash就可以了
LCP可以用二分来做
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<algorithm>
#include<string>
using namespace std;
const unsigned long long Mod1=131ll,Mod2=171ll;
int n,q;
string s;
char ch[1000005];
unsigned long long hash1[1000005],hash2[1000005],Pow1[1000005],Pow2[1000005];
void MakeHash(){
n=s.length();
hash1[n-1]=s[n-1];
hash2[n-1]=s[n-1];
for(int i=n-2;i>=0;i--){
hash1[i]=hash1[i+1]*Mod1+s[i];
hash2[i]=hash2[i+1]*Mod2+s[i];
}
}
void Prepare(){
Pow1[0]=1ll;
Pow2[0]=1ll;
for(int i=1;i<=1000000;i++){
Pow1[i]=Pow1[i-1]*Mod1;
Pow2[i]=Pow2[i-1]*Mod2;
}
}
pair<unsigned long long,unsigned long long> GetHash(int l,int len){
return make_pair(hash1[l]-hash1[l+len]*Pow1[len],hash2[l]-hash2[l+len]*Pow2[len]);
}
int LCP(int a,int b){
if(a>b)swap(a,b);
int l=0,r=n-b;
while(l<=r){
int mid=l+r>>1;
if(GetHash(a,mid)!=GetHash(b,mid))r=mid-1;
else l=mid+1;
}
return r;
}
int main(){
freopen("2105.in","r",stdin);
freopen("2105.out","w",stdout);
scanf("%d %d",&n,&q);
scanf("%s",ch);s=ch;
Prepare();
MakeHash();
while(q--){
char opt[10];
scanf("%s",opt);
if(opt[0]=='L'){
int l,r;
scanf("%d %d",&l,&r);
l--;r--;
printf("%d\n",LCP(l,r));
}
if(opt[0]=='A'){
int x;
scanf("%d %s",&x,ch);
x--;
s.insert(x,ch);
MakeHash();
}
if(opt[0]=='C'){
int x,y;
scanf("%d %d %s",&x,&y,ch);
x--;y--;
for(int i=x;i<=y;i++)s[i]=ch[i-x];
MakeHash();
}
if(opt[0]=='D'){
int x,y;
scanf("%d %d",&x,&y);
x--;y--;
s.erase(x,y-x+1);
MakeHash();
}
}
return 0;
}