ACdream 1104 瑶瑶想找回文串(SplayTree + Hash + 二分)

时间:2023-03-09 16:01:36
ACdream 1104 瑶瑶想找回文串(SplayTree + Hash + 二分)

Problem Description

刚学完后缀数组求回文串的瑶瑶(tsyao)想到了另一个问题:如果能够对字符串做一些修改,怎么在每次询问时知道以某个字符为中心的最长回文串长度呢?因为瑶瑶整天只知道LOL,当他知道自己省选成绩的时候就天天在LOL,导致现在的她实在是太弱了,根本解决不了这个问题,于是就来找你帮忙,么么哒~你就帮帮她吗ACdream 1104 瑶瑶想找回文串(SplayTree + Hash + 二分)

Input

第一行为一个长度不超过100000字符串s作为初始字符串。第二行一个正整数n,表示操作/询问的个数。接下来n行,每行有如下几种可能出现的操作/询问:

Insert a x  在a处字符的后面插入一个字符x

Delete a  把a处字符删除

Update a x 把a处字符改为x

Query a 查询以a为中心的最长回文串长度

Output

对于每个询问,输出得到的最长回文串长度

题目大意:略。

思路:

——————————————————————————————————————————————————————————

搬一下官方(?)题解:http://tsyao.tk/archives/94

SPLAY保存改区间从左向右的hash值和从右向左的hash值,对于每个询问,二分字符串长度。总的时间复杂度是O(qlognlogn)

——————————————————————————————————————————————————————————

处理技巧:头尾加上一个空字符可以不用考虑边界的情况。

代码(1932MS):

 #include <cstdio>
#include <iostream>
#include <cstring>
#include <algorithm>
using namespace std;
typedef long long LL; const int MAXN = ;
const int MOD = 1e8 + ;
const LL seed = ; LL base[MAXN];
char s[MAXN], op[];
int n, m; void initBase(int n = ) {
base[] = ;
for(int i = ; i <= n; ++i) base[i] = base[i - ] * seed % MOD;
} struct SplayTree {
struct Node {
int size, lhash, rhash;
char c;
Node *fa, *ch[];
};
Node statePool[MAXN], *nil, *root;
int stk[MAXN], top;
int ncnt; SplayTree() {
nil = statePool;
} void init() {
ncnt = ;
top = ;
} Node* new_node(char v, Node* f) {
Node* t;
if(top) t = &statePool[stk[--top]];
else t = &statePool[ncnt++];
t->size = ;
t->lhash = t->rhash = t->c = v;
t->ch[] = t->ch[] = nil;
t->fa = f;
return t;
} void del_node(Node* &x) {
stk[top++] = x - statePool;
x = nil;
} void update(Node* x) {
int s0 = x->ch[]->size, s1 = x->ch[]->size;
x->size = s0 + s1 + ;
x->lhash = (x->ch[]->lhash * base[s1 + ] + x->c * base[s1] + x->ch[]->lhash) % MOD;
x->rhash = (x->ch[]->rhash * base[s0 + ] + x->c * base[s0] + x->ch[]->rhash) % MOD;
} void rotate(Node* x) {
Node* y = x->fa;
int t = (y->ch[] == x);
y->fa->ch[y->fa->ch[] == y] = x; x->fa = y->fa;
y->ch[t] = x->ch[t ^ ]; x->ch[t ^ ]->fa = y;
x->ch[t ^ ] = y; y->fa = x;
update(y);
} void splay(Node* x, Node* f) {
while(x->fa != f) {
if(x->fa->fa == f) rotate(x);
else {
Node *y = x->fa, *z = y->fa;
if((z->ch[] == y) == (y->ch[] == x)) rotate(y);
else rotate(x);
rotate(x);
}
}
update(x);
if(x->fa == nil) root = x;
} Node* kth(int k) {
Node* x = root;
while(true) {
int t = x->ch[]->size + ;
if(t == k) break;
if(t > k) x = x->ch[];
else x = x->ch[], k -= t;
}
return x;
} void build(Node* &x, Node* f, int l, int r) {
int mid = (l + r) >> ;
x = new_node(s[mid], f);
if(l < mid) build(x->ch[], x, l, mid - );
if(mid < r) build(x->ch[], x, mid + , r);
update(x);
} void insert(int pos, char c) {
splay(kth(pos), nil);
splay(kth(pos + ), root);
root->ch[]->ch[] = new_node(c, root->ch[]);
update(root->ch[]); update(root);
} void modify(int pos, char c) {
splay(kth(pos), nil);
root->c = c;
update(root);
} void remove(int pos) {
splay(kth(pos - ), nil);
splay(kth(pos + ), root);
del_node(root->ch[]->ch[]);
update(root->ch[]); update(root);
} bool check(int pos, int len) {
splay(kth(pos - len - ), nil);
splay(kth(pos + len + ), root);
splay(kth(pos), root->ch[]);
Node* x = root->ch[]->ch[];
return x->lhash == x->rhash;
} int query(int pos) {
int l = , r = min(pos - , root->size - - pos) + ;
while(l < r) {
int mid = (l + r) >> ;
if(check(pos, mid)) l = mid + ;
else r = mid;
}
return * l - ;
} void debug(Node* x) {
static int t = ;
if(x == root) printf("Debug %d\n", ++t);
printf("val:%d lson:%d rson:%d lhash:%d rhash:%d\n", x - statePool, x->ch[] - statePool, x->ch[] - statePool, x->lhash, x->rhash);
if(x->ch[] != nil) debug(x->ch[]);
if(x->ch[] != nil) debug(x->ch[]);
}
} splay; int main() {
scanf("%s", s + );
n = strlen(s + );
initBase();
splay.init();
splay.build(splay.root, splay.nil, , n + );
scanf("%d", &m);
char c;
for(int i = , a; i < m; ++i) {
scanf("%s%d", op, &a);
++a;
if(strcmp(op, "Insert") == ) {
scanf(" %c", &c);
splay.insert(a, c);
}
if(strcmp(op, "Delete") == )
splay.remove(a);
if(strcmp(op, "Update") == ) {
scanf(" %c", &c);
splay.modify(a, c);
}
//splay.debug(splay.root);
if(strcmp(op, "Query") == )
printf("%d\n", splay.query(a));
}
}