bzoj1014
splay+二分+哈希
splay维护区间哈希值,每次二分长度
调了很长时间,主要是两个错误:1.提取区间应该是pos+1,pos+2,因为现在在开头放了一个?,所以现在应该是位置比pos+1大,比pos+2小 2.二分边界,因为多加了两个字符,所以原串长度应该是cnt-2,那么二分边界应该是-1->len+1,也就是-1>cnt-y,因为cnt=n+2,串的最大长度应该小于结尾,所以y+len-1<=n,y+len-1<=cnt-2,所以应该是len<=cnt-y-1,又因为二分边界应该比上界大一,所以是cnt-y
原先的姿势太丑陋了,就新抄了个模板
#include<bits/stdc++.h> using namespace std; const int N = 400010; const int seed = 19992147; int n, root, m; int pw[N]; char s[N]; struct Splay { int cnt; int child[N][2], fa[N], key[N], size[N], h[N]; char k[N]; void dfs(int x) { if(child[x][0]) dfs(child[x][0]); printf("%c", k[x]); if(child[x][1]) dfs(child[x][1]); } inline bool wh(int x) { return child[fa[x]][1] == x; } inline void update(int x) { h[x] = (h[child[x][0]] * seed + key[x]) * pw[size[child[x][1]]] + h[child[x][1]]; size[x] = size[child[x][0]] + size[child[x][1]] + 1; } inline void rotate(int x) { int y = fa[x], z = fa[y], t = wh(x); fa[x] = z; child[z][wh(y)] = x; child[y][t] = child[x][t ^ 1]; fa[child[x][t ^ 1]] = y; child[x][t ^ 1] = y; fa[y] = x; update(y); update(x); } inline void splay(int x, int t) { if(fa[x] == t) return; for(int f; (f = fa[x]) != t; rotate(x)) if(fa[f] != t) rotate((wh(x) == wh(f)) ? f : x); if(!t) root = x; update(root); } inline void build(int l, int r, int &x, char s[], int last) { if(l > r) return; int mid = (l + r) >> 1; key[x = ++cnt] = s[mid] - 'a'; k[cnt] = s[mid]; fa[x] = last; build(l, mid - 1, child[x][0], s, x); build(mid + 1, r, child[x][1], s, x); update(x); } inline void insert(int pos, char s[]) { int t, x = find(root, pos + 1), y = find(root, pos + 2); splay(x, 0); splay(y, root); child[child[root][1]][0] = ++cnt; fa[cnt] = child[root][1]; key[cnt] = s[0] - 'a'; k[cnt] = s[0]; update(cnt); update(child[root][1]); update(root); } inline int find(int x, int k) { if(size[child[x][0]] + 1 == k) return x; if(size[child[x][0]] >= k) return find(child[x][0], k); return find(child[x][1], k - size[child[x][0]] - 1); } inline void change(int pos, char s[]) { int x = find(root, pos + 1); splay(x, 0); key[root] = s[0] - 'a'; k[root] = s[0]; update(root); } inline int Hash(int x, int y) { x = find(root, x); y = find(root, y + 2); splay(x, 0); splay(y, root); return h[child[y][0]]; } inline bool check(int x, int y, int len) { // if(x + len - 1 > cnt - 2 || y + len - 1 > cnt - 2) return false; return (Hash(x, x + len - 1) == Hash(y, y + len - 1)); } inline void ask(int x, int y) { int l = -1, r = cnt - y, ans = 0; while(r - l > 1) { int mid = (l + r) >> 1; if(check(x, y, mid)) l = ans = mid; else r = mid; } printf("%d\n", ans); } } splay; int main() { // freopen("bzoj_1014.in", "r", stdin); // freopen("bzoj_1014.out", "w", stdout); scanf("%s%d", s + 2, &m); n = strlen(s + 2); pw[0] = 1; for(int i = 1; i <= N - 10; ++i) pw[i] = pw[i - 1] * seed; s[1] = '?'; ++n; s[++n] = '?'; splay.build(1, n, root, s, 0); while(m--) { char opt[10]; int x, y; scanf("%s", opt); if(opt[0] == 'Q') { scanf("%d%d", &x, &y); if(x > y) swap(x, y); splay.ask(x, y); } if(opt[0] == 'I') { scanf("%d%s", &x, s); splay.insert(x, s); } if(opt[0] == 'R') { scanf("%d%s", &x, s); splay.change(x, s); } } // fclose(stdin); // fclose(stdout); return 0; }