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 ... 
随机推荐
- importSTV的使用
			一:由HDFS将数据直接导入到HBase中 1.生成TSV文件 2.内容 3.上传到HDFS 4.运行 export HBASE_HOME=/etc/opt/modules/hbase-0.98.6- ... 
- java中计算两个日期之间天数的程序设计。
			//用java编写出一个以下方法计算两个日期之间天数的程序设计. import java.util.regex.Matcher; import java.util.regex.Pattern; pub ... 
- zepto源码--几个判断函数--学习笔记
			几个需要经常用到的类型判断: 自定义一个类似于typeof的函数,提供更多的类型判断. class2type[toString.call(obj)] 是对class2type的取值 在后面通过循环对c ... 
- const 修饰函数
			At the very first ,I got a problem . Vector Vector::operator+(const Vector &v)const{ return Vect ... 
- interview review
			缘起: 因为最近要找工作,自己总结了一下面试的注意事项. 1自我介绍方法 1.基本情况:姓名.年龄.学历.家庭与理想. 简单明了,不要啰嗦. 2.学习能力:专业知识.勤奋好学. 用事实说明学习能力不错 ... 
- 让UITableView 的 headerView跟随 cell一起滚动,tableHeaderView
			在进行UITableView开发的时候,我们有时希望在cell的上面放置一些按钮之类的空间,又想让这些空间跟着cell一起滚动,刚开始想着hederView,注意,这是tableView的sectio ... 
- 如何更改Magento的Base URL
			Magento的Base URL是用于访问商店页面的URL,您也可以为单独一个store view设置一个Base Url.在改这项值之前请确保您的域名已经指向了网站所在服务器的IP,DNS解析完成后 ... 
- [LeetCode]题解(python):040-Combination Sum II
			题目来源 https://leetcode.com/problems/combination-sum-ii/ Given a collection of candidate numbers (C) a ... 
- 【python】RGB图片到灰度图的转换
			在做立体匹配求深度图的时候遇到这个问题,用惯了matlab的rgb2gray,倒是不熟悉python的实现,在网上找到了相关方案,记下来已作备用 RGB到灰度图转换公式: Y' = 0.299 R + ... 
- django中嵌入百度editor插件
			一.安装和配置步骤: 1.先下载百度ueditor插件,并安装pip install DjangoUeditor 2.把下载好的ueditor插件放到自己的项目中 3.配置setting INSTAL ... 
