ACdream 1104 瑶瑶想找回文串(SplayTree + Hash + 二分)
Problem Description
刚学完后缀数组求回文串的瑶瑶(tsyao)想到了另一个问题:如果能够对字符串做一些修改,怎么在每次询问时知道以某个字符为中心的最长回文串长度呢?因为瑶瑶整天只知道LOL,当他知道自己省选成绩的时候就天天在LOL,导致现在的她实在是太弱了,根本解决不了这个问题,于是就来找你帮忙,么么哒~你就帮帮她吗
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));
}
}
ACdream 1104 瑶瑶想找回文串(SplayTree + Hash + 二分)的更多相关文章
- [CSP-S模拟测试]:回文串(hash+二分)
题目描述 $ASDFZ$的机房中不仅有红太阳,还有蓝太阳和原谅色太阳.有一天,太阳们来到机房,发现桌上有不知道哪个蒟蒻放上的问题:令$F(A,B)$表示选择一个串$A$的非空前缀$S$和串$B$的非空 ...
- HDU - 6156 2017CCPC网络赛 Palindrome Function(数位dp找回文串)
Palindrome Function As we all know,a palindrome number is the number which reads the same backward a ...
- bzoj 3676 回文串 manachar+hash
考虑每个回文串,它一定是它中心字母的最长回文串两侧去掉同样数量的字符后的一个子串. 所以我们可以用manachar求出每一位的回文半径,放到哈希表里并标记出它的下一个子串. 最后拓扑排序递推就行了.. ...
- POWEROJ 2610 判断回文串 【HASH】
题目链接[https://www.oj.swust.edu.cn/problem/show/2610] 题意:给你一个字符串,让你判断这个字符串是不是回文串,字符串的长度是1<len<1e ...
- [BZOJ4755][JSOI2016]扭动的回文串(manacher+Hash)
前两种情况显然直接manacher,对于第三种,枚举回文中心,二分回文半径,哈希判断即可. #include<cstdio> #include<algorithm> #defi ...
- POJ--3974 Palindrome(回文串,hash)
链接:点击这里 #include<iostream> #include<algorithm> #include<stdio.h> #include<cstri ...
- 【回文串-Manacher】
Manacher算法能够在O(N)的时间复杂度内得到一个字符串以任意位置为中心的回文子串.其算法的基本原理就是利用已知回文串的左半部分来推导右半部分. 转:http://blog.sina.com.c ...
- 【BZOJ】【2565】最长双回文串
Manacher算法 找出一个最长子串S=X+Y,且X和Y都是回文串,求最长的长度是多少…… 同时找两个串明显很难搞啊……但是我们可以先找到所有的回文串!在找回文串的同时我们可以预处理出来l[i]和r ...
- 回文串 --- 动态dp UVA 11584
题目链接: https://cn.vjudge.net/problem/34398/origin 本题的大意其实很简单,就是找回文串,大致的思路如下: 1. 确定一个回文串,这里用到了自定义的chec ...
随机推荐
- [daily][optimize] 一个小python程序的性能优化 (python类型转换函数引申的性能优化)
前天,20161012,到望京面试.第四个职位,终于进了二面.好么,结果人力安排完了面试时间竟然没有通知我,也没有收到短信邀请.如果没有短信邀请门口的保安大哥是不让我进去大厦的.然后,我在11号接到了 ...
- Cookie操作
1.写cookie方法 #region 登录时写入cookie public static void LoginCookieSave(string uid, string loginname, str ...
- nrf51822裸机教程-硬件timer
该讲介绍51822的Timer/Counter模块工作在timer模式下(定时器模式,还可以工作为计数器模式) 如何操作 51822的Timer/Counter结构如下图所示 Timer模块从PCLK ...
- Socket通信原理探讨(C++为例) good
http://www.cnblogs.com/xufeiyang/articles/4878096.html http://www.cnblogs.com/xufeiyang/articles/453 ...
- 【C++】动态内存与智能指针
C++常见的内存分配方式有三种: 从静态存储区分配,这里主要是存储局部static对象,类的static成员以及定义在函数之外的变量: 从栈内存分配,这里主要是存储函数内的非static对象: 从堆内 ...
- Excel导入数据到Sql server 中出错:“文本被截断,或者一个或多个字符在目标代码页中没有匹配项”
从Excel导入数据到Sql server 时,由于表中的数据有的很长,导入时出现如下错误(如果数据不是很长,255内以内,则不会出现错误): 出错原因: SQL Server的导入导出为了确定数据表 ...
- Condition
1.Condition是个接口,其实现类是同步器里面的一个内部静态类:ConditionObject. 2.Lock是个接口,该接口里面有个方法是:Condition newCondition(); ...
- .NET(c#)new关键字的三种用法
前几天去家公司面试,有一道这样的题:写出c#中new关键字的三种用法,思前想后挖空心思也只想出了两种用法,回来查了下msdn,还真是有第三种用法:用于在泛型声明中约束可能用作类型参数的参数的类型,这是 ...
- jquery中奖实例代码
<!doctype html> <html> <head> <meta http-equiv="Content-Type" content ...
- centos python 2.7 安装
一开始有这个需求,是因为用 YaH3C 替代 iNode 进行校园网认证时,一直编译错误,提示找不到 Python 的某个模块,百度了一下,此模块是在 Python2.7 以上才有的,但是系统的自带的 ...