加入插入之后,可以用Splay维护区间hash值,然后类似上面,只是需要额外的O(log(L))的时间提取出区间,单次询问的时间复杂度为O(log(L) * log(L))
#include <cstdio>
#include <cstring>
const int maxn = 110000 + 10;
typedef unsigned long long ll;
const ll seed = 131;
char val[maxn];
int tot, root, fa[maxn], son[maxn][2], siz[maxn], cnt = 0;
ll hash[maxn], pow[maxn];
inline void PushUp(int rt){
siz[rt] = siz[son[rt][0]] + siz[son[rt][1]] + 1;
hash[rt] = hash[son[rt][0]] + val[rt] * pow[siz[son[rt][0]]] + hash[son[rt][1]] * pow[siz[son[rt][0]] + 1];
}
inline void Rotate(int x){
int f = fa[x], p = son[f][0] == x;
son[f][!p] = son[x][p];
fa[son[x][p]] = f;
fa[x] = fa[f];
if(fa[x]) son[fa[x]][son[fa[x]][1] == f] = x;
son[x][p] = f;
fa[f] = x;
PushUp(f);
}
inline void Splay(int x, int t){
int y, z;
while(fa[x] != t){
if(fa[fa[x]] == t) Rotate(x);
else{
y = fa[x];
z = fa[y];
if(son[y][1] == x ^ son[z][1] == y) Rotate(x);
else Rotate(y);
Rotate(x);
}
}
PushUp(x);
if(!t) root = x;
}
inline void Find(int kth, int t){
int x = root, tmp;
while(x){
tmp = siz[son[x][0]];
if(kth == tmp + 1){
Splay(x, t);
return;
}
else if(kth < tmp + 1) x = son[x][0];
else{
x = son[x][1];
kth -= tmp + 1;
}
}
}
char s[maxn];
int Insert(int st, int en){
if(st > en) return 0;
int mid = st + en >> 1, now = ++cnt;
val[now] = s[mid];
son[now][0] = Insert(st, mid - 1);
if(son[now][0]) fa[son[now][0]] = now;
son[now][1] = Insert(mid + 1, en);
if(son[now][1]) fa[son[now][1]] = now;
PushUp(now);
return now;
}
inline void LCQ(){
int x, y;
scanf("%d %d", &x, &y);
int l = 1, r = tot, mid, ret = 0;
ll tmp;
while(l <= r){
mid = l + r >> 1;
if(y + mid - 1 > tot) r = mid - 1;
else{
Find(x, 0);
Find(x + mid + 1, root);
tmp = hash[son[son[root][1]][0]];
Find(y, 0);
Find(y + mid + 1, root);
if(tmp == hash[son[son[root][1]][0]]){
ret = mid;
l = mid + 1;
}
else r = mid - 1;
}
}
printf("%d\n", ret);
}
int main(){
pow[0] = 1;
for(int i = 1; i < maxn; i++)
pow[i] = pow[i - 1] * seed;
siz[0] = hash[0] = fa[0] = son[0][0] = son[0][1] = 0;
scanf("%s", s + 1);
tot = strlen(s + 1);
root = Insert(0, tot + 1);
int m;
scanf("%d", &m);
char opt[5], d[5];
int x, y, t;
while(m--){
scanf("%s", opt);
switch(opt[0]){
case ‘I‘:
scanf("%d%s", &x, d);
Find(x + 1, 0);
Find(x + 2, root);
cnt++;
val[cnt] = d[0];
fa[cnt] = son[root][1];
son[son[root][1]][0] = cnt;
PushUp(cnt);
PushUp(son[root][1]);
PushUp(root);
tot++;
break;
case ‘R‘:
scanf("%d%s", &x, d);
Find(x, 0);
Find(x + 2, root);
t = son[son[root][1]][0];
val[t] = d[0];
PushUp(t);
PushUp(son[root][1]);
PushUp(root);
break;
case ‘Q‘:
LCQ();
break;
}
}
return 0;
}