P4036 [JSOI2008]火星人 解题报告
Description
给定一个初始的字符串 , 次操作。
- 给定,求出 和 的最长公共前缀。
- 给定,将 位置 的字符改为 。
- 给定,在 位置 后加入一个字符 。
Solution
求最长公共前缀可以用二分 + 字符串hash。
问题转化为维护 hash 值。
序列操作,想到平衡树。这里我用的是 Splay。
~~其实是个 平衡树维护hash板题了。~~
Code

#include<bits/stdc++.h> using namespace std; #define ull unsigned long long inline int read() { int x = 0, f = 1; char c = getchar(); while (c < '0' || c > '9') {if (c == '-') f = -f; c = getchar();} while (c >= '0' && c <= '9') {x = (x << 3) + (x << 1) + (c ^ 48); c = getchar();} return x * f; } const int N = 1e6 + 10, base = 233; int n, m; ull pw[N]; char s[N]; namespace Splay { int rt, tot, val[N], sz[N], fa[N], ch[N][2]; ull hs[N]; inline void maintain(int x) { sz[x] = sz[ch[x][0]] + sz[ch[x][1]] + 1; hs[x] = hs[ch[x][0]] + val[x] * pw[sz[ch[x][0]]] + hs[ch[x][1]] * pw[sz[ch[x][0]] + 1]; } inline bool get(int x) {return x == ch[fa[x]][1];} inline void rotate(int x) { int y = fa[x], z = fa[y], chk = get(x); ch[y][chk] = ch[x][chk^1]; if (ch[x][chk^1]) fa[ch[x][chk^1]] = y; ch[x][chk^1] = y; fa[y] = x; fa[x] = z; if (z) ch[z][y == ch[z][1]] = x; maintain(y); maintain(x); } inline void build(int l, int r, int x) { if (l > r) return; int mid = l + r >> 1; if (mid >= x) ch[x][1] = mid; else ch[x][0] = mid; fa[mid] = x; sz[mid] = 1; if (l == r) return; build(l, mid-1, mid); build(mid+1, r, mid); maintain(mid); return; } inline void splay(int x, int goal) { for (int f; (f = fa[x]) != goal; rotate(x)) if (fa[f] != goal) rotate(get(x) == get(f) ? f : x); if (!goal) rt = x; } inline int find(int x) { int p = rt; while (1) { if (sz[ch[p][0]] + 1 == x) return p; if (sz[ch[p][0]] + 1 < x) x -= sz[ch[p][0]] + 1, p = ch[p][1]; else p = ch[p][0]; } } inline ull get_hash(int l, int r) { int x = find(l), y = find(r + 2); splay(x, 0); splay(y, rt); return hs[ch[ch[rt][1]][0]]; } } using namespace Splay; int main () { scanf("%s", s + 1); n = strlen(s + 1); m = read(); pw[0] = 1; for (int i = 1; i <= n+m; ++ i) pw[i] = pw[i-1] * base; for (int i = 2; i <= n + 1; ++ i) hs[i] = val[i] = s[i-1] - 'a' + 1; build(1, n+2, 0); rt = (n+3) >> 1; tot = n + 2; while (m --) { char opt; scanf(" %c", &opt); if (opt == 'Q') { int x = read(), y = read(); if (x > y) swap(x, y); int l = 0, r = tot - y - 1, ans = 0; while (l <= r) { int mid = l + r >> 1; if (get_hash(x, x + mid - 1) == get_hash(y, y + mid - 1)) ans = mid, l = mid + 1; else r = mid - 1; } printf("%d\n", ans); } else if (opt == 'R') { int x = read(); char d; scanf(" %c", &d); splay(find(x + 1), 0); val[rt] = d - 'a' + 1; maintain(rt); } else if (opt == 'I') { int p = read(); char d; scanf(" %c", &d); int x = find(p+1), y = find(p+2); splay(x, 0); splay(y, rt); ch[ch[rt][1]][0] = ++ tot; fa[tot] = ch[rt][1]; val[tot] = hs[tot] = d - 'a' + 1; splay(tot, 0); } } return 0; }
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 地球OL攻略 —— 某应届生求职总结
· 周边上新:园子的第一款马克杯温暖上架
· Open-Sora 2.0 重磅开源!
· 提示词工程——AI应用必不可少的技术
· .NET周刊【3月第1期 2025-03-02】