BZOJ 1014 火星人 | 平衡树维护哈希
BZOJ 1014 火星人
题意
有一个字符串,三中操作:在某位置后面插入一个字符、修改某位置的字符、询问两个后缀的最长公共前缀。
题解
看到网上的dalao们都说这道题是平衡树,我就很懵x……平衡树维护什么啊?
最后发现某个节点维护的是它所代表的区间的哈希值——显然这个哈希值可以从左右子树的哈希值和这个节点上的字符算出来。
#include <cstdio>
#include <cmath>
#include <cstring>
#include <algorithm>
#define space putchar(' ')
#define enter putchar('\n')
using namespace std;
typedef unsigned long long ll;
template <class T>
void read(T &x){
char c;
bool op = 0;
while(c = getchar(), c < '0' || c > '9')
if(c == '-') op = 1;
x = c - '0';
while(c = getchar(), c >= '0' && c <= '9')
x = x * 10 + c - '0';
if(op) x = -x;
}
template <class T>
void write(T x){
if(x < 0) putchar('-'), x = -x;
if(x >= 10) write(x / 10);
putchar('0' + x % 10);
}
const int N = 100005, B = 29;
int n, m;
int idx, root, fa[N], ls[N], rs[N], val[N], sze[N];
ll hsh[N], pw[N];
char s[N];
#define which(x) (ls[fa[(x)]] == (x))
void upt(int u){
sze[u] = sze[ls[u]] + sze[rs[u]] + 1;
hsh[u] = hsh[ls[u]] + val[u] * pw[sze[ls[u]]] + hsh[rs[u]] * pw[sze[ls[u]] + 1];
}
void rotate(int u){
int v = fa[u], w = fa[v], b = which(u) ? rs[u] : ls[u];
if(w) which(v) ? ls[w] = u : rs[w] = u;
which(u) ? (ls[v] = b, rs[u] = v) : (rs[v] = b, ls[u] = v);
fa[u] = w, fa[v] = u;
if(b) fa[b] = v;
upt(v), upt(u);
}
void splay(int u, int tar){
while(fa[u] != tar){
if(fa[fa[u]] != tar){
if(which(u) == which(fa[u])) rotate(fa[u]);
else rotate(u);
}
rotate(u);
}
if(!tar) root = u;
}
int build(int l, int r, int pre){
if(l > r) return 0;
int u = ++idx, mid = (l + r) >> 1;
val[u] = s[mid] - 'a' + 1, fa[u] = pre;
ls[u] = build(l, mid - 1, u);
rs[u] = build(mid + 1, r, u);
upt(u);
return u;
}
int find(int x){
int u = root;
while(sze[ls[u]] != x)
if(x <= sze[ls[u]] - 1) u = ls[u];
else x -= sze[ls[u]] + 1, u = rs[u];
return u;
}
void insert(int pos, int x){
int u = find(pos), v = find(pos + 1);
splay(u, 0), splay(v, u);
ls[v] = ++idx, fa[idx] = v, val[idx] = x, sze[idx] = 1;
splay(idx, 0);
}
void change(int pos, int x){
int u = find(pos);
val[u] = x;
splay(u, 0);
}
ll gethsh(int pos, int len){
int u = find(pos - 1), v = find(pos + len);
splay(u, 0), splay(v, u);
return hsh[ls[v]];
}
int query(int a, int b){
int l = 0, r = sze[root] - max(a, b) - 1, mid;
while(l < r){
mid = (l + r + 1) >> 1;
if(gethsh(a, mid) == gethsh(b, mid)) l = mid;
else r = mid - 1;
}
return l;
}
int main(){
scanf("%s", s + 1);
n = strlen(s + 1);
pw[0] = 1;
for(int i = 1; i < N; i++)
pw[i] = pw[i - 1] * B;
root = build(0, n + 1, 0);
read(m);
while(m--){
char op[2];
scanf("%s", op);
if(op[0] == 'Q'){
int a, b;
read(a), read(b);
write(query(a, b)), enter;
}
else if(op[0] == 'I'){
int pos;
scanf("%d%s", &pos, op);
insert(pos, op[0] - 'a' + 1);
}
else if(op[0] == 'R'){
int pos;
scanf("%d%s", &pos, op);
change(pos, op[0] - 'a' + 1);
}
}
return 0;
}
BZOJ 1014 火星人 | 平衡树维护哈希的更多相关文章
- bzoj 1014 火星人prefix - 链表 - 分块
Description 火星人最近研究了一种操作:求一个字串两个后缀的公共前缀.比方说,有这样一个字符串:madamimadam,我们将这个字符串的各个字符予以标号:序号: 1 2 3 4 5 6 7 ...
- [BZOJ]1014 火星人prefix(JSOI2008)
一边听省队dalao讲课一边做题真TM刺激. BZOJ的discuss简直就是题面plus.大样例.SuperHINT.dalao题解的结合体. Description 火星人最近研究了一种操作:求一 ...
- bzoj 1014 火星人prefix —— splay+hash
题目:https://www.lydsy.com/JudgeOnline/problem.php?id=1014 用 splay 维护字符串上不同位置的哈希值还是第一次... 具体就是每个节点作为位置 ...
- BZOJ 1014 火星人prefix
Description 火星人最近研究了一种操作:求一个字串两个后缀的公共前缀.比方说,有这样一个字符串:madamimadam,我们将这个字符串的各个字符予以标号:序号: 1 2 3 4 5 6 7 ...
- BZOJ.1014.[JSOI2008]火星人(Splay 二分 Hash)
题目链接 后缀数组显然不行啊.求LCP还可以哈希+二分,于是考虑用平衡树维护哈希值. \[某一节点的哈希值 = hs[lson]*base^{sz[rson]+1} + s[rt]*base^{sz[ ...
- bzoj 1014 [JSOI2008]火星人prefix——splay+哈希
题目:https://www.lydsy.com/JudgeOnline/problem.php?id=1014 用splay维护字符串,每个点记录子树的哈希值,然后二分查询. 二分不是把两个点的哈希 ...
- [BZOJ 1014] [JSOI2008] 火星人prefix 【Splay + Hash】
题目链接:BZOJ - 1014 题目分析 求两个串的 LCP ,一种常见的方法就是 二分+Hash,对于一个二分的长度 l,如果两个串的长度为 l 的前缀的Hash相等,就认为他们相等. 这里有修改 ...
- BZOJ 1492 货币兑换 cdq分治或平衡树维护凸包
题意:链接 方法:cdq分治或平衡树维护凸包 解析: 这道题我拒绝写平衡树的题解,我仅仅想说splay不要写挂,insert边界条件不要忘.del点的时候不要脑抽d错.有想写平衡树的去看140142或 ...
- Luogu 3369 / BZOJ 3224 - 普通平衡树 - [无旋Treap]
题目链接: https://www.lydsy.com/JudgeOnline/problem.php?id=3224 https://www.luogu.org/problemnew/show/P3 ...
随机推荐
- kali虚拟机安装后操作[配置ssh,安装vmtools,更新源]
更新源 # 打开控制台, 输入以下命令打开编辑器修改配置文件 $ leafpad /etc/apt/sources.list #kali官方源 deb http://http.kali.org/kal ...
- java事务 深入Java事务的原理与应用
一.什么是JAVA事务 通常的观念认为,事务仅与数据库相关. 事务必须服从ISO/IEC所制定的ACID原则.ACID是原子性(atomicity).一致性(consistency).隔离性 (iso ...
- docker私服搭建nexus3
docker私服搭建有官方的registry镜像,也有改版后的NexusOss3.x,因为maven的原因搭建了nexus,所以一并将docker私服也搭建到nexus上. nexus的安装过程就单独 ...
- Netty源码分析第2章(NioEventLoop)---->第2节: NioEventLoopGroup之NioEventLoop的创建
Netty源码分析第二章: NioEventLoop 第二节: NioEventLoopGroup之NioEventLoop的创建 回到上一小节的MultithreadEventExecutorG ...
- Maven ResourceBundle.getBundle读取Properties异常MissingResourceException: Can't find bundlei解决方法
参考:https://blog.csdn.net/thousa_ho/article/details/72817616 问题描述 ResourceBundle读取properties配置文件提示 Mi ...
- 云计算时代,传统企业 IT 从业者如何做好转型?
本文来源于国外社区 DZone,作者 Dennis O'Reilly 撰写过多篇关于云计算.混合云等内容的文章,本文内容围绕云计算时代,企业纷纷上云,传统 IT 从业者如何做好转型. 本文由“数梦工场 ...
- node jade模板数据库操作
/* Navicat MySQL Data Transfer Source Server : localhost Source Server Version : 50519 Sourc ...
- Dao DaoImp
DAO层:DAO层主要是做数据持久层的工作,负责与数据库进行联络的一些任务都封装在此,DAO层的设计首先是设计DAO的接口,然后在Spring的配置文件中定义此接口的实现类,然后就可在模块中调用此接口 ...
- Beta版发布 - 感谢有你们
在本次Beta版开发的过程中,很感谢组长王航对我的信任,让我统筹大家的工作任务和进度,使我对项目管理有了深刻的理解. 我也要感谢邹双黛,在beta版开发中因为邹双黛的帮助,我对于文字类工作已经越来越得 ...
- java实验2实验报告(20135232王玥)
实验二 Java面向对象程序设计 一.实验内容 1. 初步掌握单元测试和TDD 2. 理解并掌握面向对象三要素:封装.继承.多态 3. 初步掌握UML建模 4. 熟悉S.O.L.I.D原则 5. 了解 ...