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 + 二分)的更多相关文章

  1. [CSP-S模拟测试]:回文串(hash+二分)

    题目描述 $ASDFZ$的机房中不仅有红太阳,还有蓝太阳和原谅色太阳.有一天,太阳们来到机房,发现桌上有不知道哪个蒟蒻放上的问题:令$F(A,B)$表示选择一个串$A$的非空前缀$S$和串$B$的非空 ...

  2. HDU - 6156 2017CCPC网络赛 Palindrome Function(数位dp找回文串)

    Palindrome Function As we all know,a palindrome number is the number which reads the same backward a ...

  3. bzoj 3676 回文串 manachar+hash

    考虑每个回文串,它一定是它中心字母的最长回文串两侧去掉同样数量的字符后的一个子串. 所以我们可以用manachar求出每一位的回文半径,放到哈希表里并标记出它的下一个子串. 最后拓扑排序递推就行了.. ...

  4. POWEROJ 2610 判断回文串 【HASH】

    题目链接[https://www.oj.swust.edu.cn/problem/show/2610] 题意:给你一个字符串,让你判断这个字符串是不是回文串,字符串的长度是1<len<1e ...

  5. [BZOJ4755][JSOI2016]扭动的回文串(manacher+Hash)

    前两种情况显然直接manacher,对于第三种,枚举回文中心,二分回文半径,哈希判断即可. #include<cstdio> #include<algorithm> #defi ...

  6. POJ--3974 Palindrome(回文串,hash)

    链接:点击这里 #include<iostream> #include<algorithm> #include<stdio.h> #include<cstri ...

  7. 【回文串-Manacher】

    Manacher算法能够在O(N)的时间复杂度内得到一个字符串以任意位置为中心的回文子串.其算法的基本原理就是利用已知回文串的左半部分来推导右半部分. 转:http://blog.sina.com.c ...

  8. 【BZOJ】【2565】最长双回文串

    Manacher算法 找出一个最长子串S=X+Y,且X和Y都是回文串,求最长的长度是多少…… 同时找两个串明显很难搞啊……但是我们可以先找到所有的回文串!在找回文串的同时我们可以预处理出来l[i]和r ...

  9. 回文串 --- 动态dp UVA 11584

    题目链接: https://cn.vjudge.net/problem/34398/origin 本题的大意其实很简单,就是找回文串,大致的思路如下: 1. 确定一个回文串,这里用到了自定义的chec ...

随机推荐

  1. 设置MyEclipse开发项目时使用的JDK

    安装好MyEclipse之后,在MyEclipse中开发项目时,默认使用的是MyEclipse是自带的JDK,如下图所示: 如果我们需要使用自己安装好的JDK,那么就需要在MyEclipse中重新设置 ...

  2. 如何获取并分析L2CAP包

    本文中的分析与软件相关的内容,都是以WinCE中的 Microsoft Bluetooth Core Stack为例进行分析:与协议有关的内容,是基于Bluetooth Core 2.1 + EDR ...

  3. nrf51822裸机教程-SPI(主)

    关于SPI总线的介绍这里就不细说了,网上有很多介绍SPI总线时序的. SPI总线的本质就是一个环形总线结构,在时钟驱动下两个双向移位寄存器进行数据交换. 所以SPI总线的特色就是:传输一字节数据的同时 ...

  4. windbg 命令 gchandles

    使用windbg导出dump文件 .dump /ma D:\testdump.dmp gchandles命令列出句柄,同时列出句柄引用的对象,演示代码如下: using System; using S ...

  5. HBase的数据迁移(含HDFS的数据迁移)

    1.启动两个HDFS集群 hadoop0,hadoop1,都是伪分布式的集群 2.启动hadoop3的zookeeper与hbase 注意点:需要开启yarn服务,因为distcp需要yarn. 3. ...

  6. firs tday

    1.JVM 解析: 2.JDBC 解析: 3.Spring

  7. 在Windows上一键编译各种版本的Protobuf

    所需工具 : cmake  for  windows 和  git for windows 原理:protobuf 是google的一个开源项目,其源代码在github上可以下载到,并且源码都采用cm ...

  8. 20145211 《Java程序设计》实验报告二:Java面向对象程序设计

    实验要求 初步掌握单元测试和TDD 理解并掌握面向对象三要素:封装.继承.多态 初步掌握UML建模 熟悉S.O.L.I.D原则 了解设计模式 实验内容 单元测试 面向对象三要素 设计模式初步 练习 实 ...

  9. 修改PHP的memory_limit限制

    在运行PHP程序,通常会遇到“Fatal Error: Allowed memory size of xxxxxx bytes exhausted”的错误, 这个意味着PHP脚本使用了过多的内存,并超 ...

  10. LeetCode Factorial Trailing Zeroes

    原题链接在这里:https://leetcode.com/problems/factorial-trailing-zeroes/ 求factorial后结尾有多少个0,就是求有多少个2和5的配对. 但 ...