这道题需要用到一个叫Rabin-Karp的算法 自行百度或者看算导 不作解释
可以看的出来这是一个字符串匹配的题目 单由于一些特殊的插入操作 使得其本身变得难以维护 所以引入splay进行维护
对于树中的每一个节点 保存以其为根的子树的RK值(要包括左右子树 自己放在左右子树中间) 这样我们就可以快速的找到一个字符串的RK值
对于RK值的维护 可在splay旋转过程中利用左右儿子的RK值 直接进行计算 算式如下
RK = ( ((LL)ch[0]->RK * base[ch[1]->sz+1]) % p + ((LL)key * base[ch[1]->sz]) % p + ch[1]->RK) % p;
base代表了28进制数中第i位的位权 这样可以用O(1)的复杂度快速的进行RK值的更新 这本身也是RK算法的一大优势
对于其中的R操作 只需要将x旋转到根 然后修改值和RK值就可以了
对于其中的I操作 只需要将x旋转到根 将自己接到根的右儿子处 然后把根本来的右儿子变为自己的右儿子并重新计算自己和根的RK值即可
对于其中的Q操作 我们无法直接确定最大前缀和的长度 所以需要枚举 因为长度存在单调性 可以使用二分
对于每一个长度L 将x-1旋转到根 x+L-1旋转到根的右儿子处 那么长度为L的前缀字符串就正好在x+L-1的左子树 可以直接取出RK值 对于y进行相同的操作然后进行RK值匹配即可
对于选取的MOD值来说 大质数冲突的概率非常小 所以可以认为不会发生冲突 因此可以不必在RK值相同时进行暴力匹配 如果进行暴力匹配可能会导致时间超限 因为匹配可能进行相当多次
至此 本题得到解决 时间上也不会超出限制(虽然我的渣代码离超时也只差几百毫秒)
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
using namespace std;
typedef long long LL;
const int MAXN = 100000;
const int p = 199999;
int n, base[MAXN+10];
char s[MAXN+10];
struct Node {
int key, sz, cnt, RK;
Node *ch[2], *fa;
Node () {}
Node(int x, int y, int z) {
key = x; sz = y; cnt = z;
}
void Update() {
sz = ch[0]->sz + ch[1]->sz + cnt;
RK = ( ((LL)ch[0]->RK * base[ch[1]->sz+1]) % p +
((LL)key * base[ch[1]->sz]) % p +
ch[1]->RK) % p;
}
int cmp(int v) const {
if(v == key) return -1;
return v < key ? 0 : 1;
}
}nil(0, 0, 0), *NIL = &nil;
struct Splay_Tree
{
Node *root;
Node tree[MAXN+10];
int ncnt;
void init() { root = NIL; ncnt = 0 ;};
Node *NewNode() {
Node &t = tree[++ncnt];
t.ch[0] = t.ch[1] = t.fa = NIL;
t.sz = t.cnt = 1;
return &tree[ncnt];
}
void Rotate(Node *x, int d)
{
Node *y = x->fa;
y->ch[!d] = x->ch[d];
if(x->ch[d] != NIL) x->ch[d]->fa = y;
x->fa = y->fa;
if(y->fa != NIL) y->fa->ch[y->fa->ch[1] == y] = x;
x->ch[d] = y;
y->fa = x;
if(y == root) root = x;
y->Update();
}
void splay(Node *x, Node *target)
{
Node *y, *z;
while(x->fa != target)
{
y = x->fa;
z = y->fa;
if(z == target) {
if(x == y->ch[0]) Rotate(x, 1);
else Rotate(x, 0);
}
else
{
if(y == z->ch[0])
if(x == y->ch[0])
Rotate(y, 1), Rotate(x, 1);
else
Rotate(x, 0), Rotate(x, 1);
else
if(x == y->ch[1])
Rotate(y, 0), Rotate(x, 0);
else
Rotate(x, 1), Rotate(x, 0);
}
x->Update();
}
}
Node *Find_kth(Node * target, int k)
{
if(k <= target->ch[0]->sz) return Find_kth(target->ch[0], k);
if(k <= target->ch[0]->sz+1) return target;
return Find_kth(target->ch[1], k-target->ch[0]->sz-1);
}
void Build(Node * &target, int l, int r, Node *F)
{
if(r < l)
return ;
target = NewNode();
int mid = (l + r) >> 1;
target->key = s[mid];
target->fa = F;
Build(target->ch[0], l, mid-1, target);
Build(target->ch[1], mid+1, r, target);
target->Update();
}
Node *Find_kth(int k) { Node *t = Find_kth(root, k); splay(t, NIL); return t; }
};
Splay_Tree sp;
int Find_RK(int l, int r)
{
Node *t1 = sp.Find_kth(l-1);
Node *t2 = sp.Find_kth(r+1);
sp.splay(t1, NIL);
sp.splay(t2, t1);
return t2->ch[0]->RK;
}
bool check(int x, int y, int L)
{
int a, b;
a = Find_RK(x, x + L - 1);
b = Find_RK(y, y + L - 1);
return a == b;
}
void R(int x, int k)
{
Node *target = sp.Find_kth(x);
sp.splay(target, NIL);
target->key = k;
target->Update();
}
void I(int x, int key)
{
Node *target = sp.Find_kth(x);
sp.splay(target, NIL);
Node *New = sp.NewNode();
New->key = key; New->fa = target;
New->ch[1] = target->ch[1];
New->Update();
if(New->ch[1] != NIL) New->ch[1]->fa = New;
target->ch[1] = New;
target->Update();
n++;
base[n] = base[n-1] * 28;
while(base[n] > p) base[n] -= p;
}
void Q(int x, int y)
{
int l = 1, r = min(n-x, n-y), mid, ans = 0;
while(l <= r)
{
mid = (l + r) >> 1;
if(check(x, y, mid)) {
ans = max(ans, mid);
l = mid+1;
}
else
r = mid-1;
}
printf("%d\n", ans);
}
int main()
{
int m;
scanf("%s", s+1);
n = strlen(s+1);
for(int i = 1; i <= n; i++) s[i] -= 'a';
s[0] = s[n+1] = 27;
base[0] = 1; base[1] = 28;
for(int i = 2; i <= n+2; i++) base[i] = (base[i-1] * 28) % p;
sp.Build(sp.root, 0, n+1, NIL);
n += 2;
scanf("%d", &m);
for(int i = 1; i <= m; i++)
{
int x, y;
scanf("%s", s);
if(s[0] == 'R') {
scanf("%d",&x);
if(x > n-2) continue;
x++;
scanf("%s", s);
R(x,s[0]-'a');
}
else if(s[0] == 'I') {
scanf("%d",&x);
x++;
scanf("%s", s);
I(x,s[0]-'a');
}
else {
scanf("%d%d",&x,&y);
x++;y++;
Q(x,y);
}
}
}