题目链接
要求维护一个字符串,支持修改字符、插入字符以及查询两个后缀的公共前缀长度的操作。
用splay维护该字符串以及子树所代表子串的hash值,查询时二分答案,直接判hash是否相等。时间复杂度
O
(
N
l
o
g
2
N
)
O(Nlog^2N)
O(Nlog2N)
#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
using namespace std;
typedef unsigned long long ll;
const int N = 100010;
const ll MO = 19260817;//膜数
char buf;
inline int read() {
int rst = 0;
do buf = getchar(); while(! isdigit(buf));
while (isdigit(buf)) rst = rst*10 + buf - '0', buf = getchar();
return rst;
}
char str[N];
int fa[N], ch[N][2], size[N], val[N], n, m, tot, root;
ll hahash[N], power[N];
#define l(x) ch[x][0]
#define r(x) ch[x][1]
#define isRoot(x) (! fa[x])
#define kd(x) (ch[fa[x]][1] == x)
#define setChild(f, c, k) (fa[ch[f][k] = c] = f)
inline void update(int x) {
size[x] = size[l(x)] + size[r(x)] + 1;
hahash[x] = (ll)hahash[l(x)] * power[size[r(x)] + 1] + (ll)val[x] * power[size[r(x)]] + hahash[r(x)];
hahash[x] %= MO;
}
inline void init() {
power[0] = 1;
for (int i = 1; i < N; i++)
power[i] = (power[i - 1] * 26) % MO;
tot = root = n + 2;
update(1);
for (int i = 0; i < n; i++)
val[i + 2] = str[i] - 'a', setChild(i + 2, i + 1, 0), update(i + 2);
setChild(n + 2, n + 1, 0); update(n + 2);
}
inline void rotate(int x) {
int y = fa[x], t = kd(x);
setChild(y, ch[x][t^1], t);
if (isRoot(y)) fa[x] = fa[y];
else setChild(fa[y], x, kd(y));
setChild(x, y, t^1); update(y); update(x);
}
inline void splay(int x, int rt) {
while (fa[x] != rt) {
if (fa[fa[x]] != rt)
if (kd(fa[x]) == kd(x)) rotate(fa[x]);
else rotate(x); rotate(x);
} if (! rt) root = x;
}
inline int find(int sz) {
int rst = root;
while (size[l(rst)] + 1 != sz) {
if (size[l(rst)] + 1 > sz) rst = l(rst);
else sz -= size[l(rst)] + 1, rst = r(rst);
} return rst;
}
inline int pre() {
int rst = l(root);
while (r(rst)) rst = r(rst);
return rst;
}
inline int nxt() {
int rst = r(root);
while (l(rst)) rst = l(rst);
return rst;
}
inline bool judge(int length, int x, int y, int l1, int l2) {
if (! length) return true;
int r1 = find(x + length + 1), r2 = find(y + length + 1);
splay(l1, 0); splay(r1, l1); ll tmp = hahash[l(r1)];
splay(l2, 0); splay(r2, l2); return tmp == hahash[l(r2)];
}
inline int query(int x, int y) {
if (x > y) swap(x, y);
if (x == y) return n - y + 1;
int xx = find(x), yy = find(y);
int l = 0, r = n - y + 1, ans = 0;
while (l <= r) {
int mid = l + r >> 1;
if (judge(mid, x, y, xx, yy)) ans = mid, l = mid + 1;
else r = mid - 1;
} return ans;
}
inline void modify(int x, int v) {
int p = find(x + 1); splay(p, 0);
val[p] = v; update(p);
}
inline void ins(int x, int v) {
int l = find(x + 1); splay(l, 0);
int r = nxt(); splay(r, l); n++;
val[++tot] = v; update(tot);
setChild(r, tot, 0); update(r); update(l);
}
inline void print(int x) {
if (l(x)) print(l(x));
printf("%c", 'a' + val[x]);
if (r(x)) print(r(x));
}
int main() {
scanf("%s", str); n = strlen(str);
init(); m = read();
while (m--) {
scanf("%s", str);
if (*str == 'Q') {
int x = read(), y = read();
printf("%d\n", query(x, y));
} else if (*str == 'R') {
int x = read(); scanf("%s", str);
modify(x, (*str) - 'a');
} else {
int x = read(); scanf("%s", str);
ins(x, (*str) - 'a');
}
} return 0;
}