bzoj 1014 火星人prefix —— splay+hash
题目:https://www.lydsy.com/JudgeOnline/problem.php?id=1014
用 splay 维护字符串上不同位置的哈希值还是第一次...
具体就是每个节点作为位置被不断旋转,点上维护的哈希值就是此时它及其儿子这一段区间的哈希值;
要查询 LCQ,可以二分一个长度,然后把两端区间分别旋转到根,取出哈希值比较;
据说用模数会很慢,写自然溢出比较好;
因为忘记 rotate 最后要 pushup 而调了很久...注释里是另一种可以A的 rotate - splay 系列;
又加深了对 splay 的理解,它的节点表示位置关系...
代码如下:
#include<iostream> #include<cstdio> #include<cstring> #include<algorithm> #define mid ((l+r)>>1) using namespace std; typedef unsigned long long ll; int const xn=1e5+5,xm=250005; int n,m,rt,fa[xm],c[xm][2],siz[xm]; ll pw[xm],hsh[xm]; char s[xn],ch[xn]; void pushup(int x) {int ls=c[x][0],rs=c[x][1];siz[x]=siz[ls]+siz[rs]+1;hsh[x]=hsh[ls]*pw[siz[rs]+1]+(s[x]-'a'+1)*pw[siz[rs]]+hsh[rs]; } void rotate(int x,int &f) {int y=fa[x],z=fa[y],d=(c[y][1]==x);if(z)c[z][c[z][1]==y]=x; // if(y==f)f=x; else c[z][c[z][1]==y]=x;fa[x]=z; fa[y]=x; fa[c[x][!d]]=y;c[y][d]=c[x][!d]; c[x][!d]=y;pushup(y); pushup(x);//!!! } void splay(int x,int f)// {while(fa[x]!=f)// {int y=fa[x],z=fa[y];if(z!=f)// {if((c[y][0]==x)^(c[z][0]==y))rotate(x,f);else rotate(y,f);}rotate(x,f);}if(!f)rt=x; } void build(int l,int r,int lst) {if(l>r)return;if(l==r)hsh[l]=s[l]-'a'+1,siz[l]=1;else build(l,mid-1,mid),build(mid+1,r,mid);fa[mid]=lst; c[lst][mid>lst]=mid; pushup(mid); } int find(int x,int k)//找到 k 位置 {while(1){int p=c[x][0],q=c[x][1];if(siz[p]+1==k)return x;else if(siz[p]+1<k)x=q,k-=siz[p]+1;else x=p;} } void insert(int pos,char d) {s[++n]=d; hsh[n]=d-'a'+1;int x=find(rt,pos+1);//+1 因为有左右的'a'splay(x,0); x=find(rt,pos+2); splay(x,rt);// // splay(x,rt); x=find(rt,pos+2); splay(x,c[rt][1]);c[x][0]=n; siz[n]=1; fa[n]=x;pushup(x); pushup(rt); } void change(int pos,char d) {int x=find(rt,pos+1);splay(x,0);// // splay(x,rt);s[x]=d; pushup(x); } bool ck(int l,int r,int k) {ll h1=0,h2=0; // int x=find(rt,l); splay(x,rt);// // x=find(rt,l+k+1); splay(x,c[rt][1]); // x=c[rt][1];// int x=find(rt,l); splay(x,0);x=find(rt,l+k+1); splay(x,rt);h1=hsh[c[x][0]]; // x=find(rt,r); splay(x,rt);// // x=find(rt,r+k+1); splay(x,c[rt][1]); // x=c[rt][1];// x=find(rt,r); splay(x,0);x=find(rt,r+k+1); splay(x,rt);h2=hsh[c[x][0]];return h1==h2; } int query(int x,int l,int r) {int ll=0,rr=n-2-max(l,r)+1,ret=0;while(ll<=rr){int md=((ll+rr)>>1);if(ck(l,r,md))ret=md,ll=md+1;else rr=md-1;}return ret; } void init() {n=strlen(s+2); pw[0]=1;for(int i=1;i<=xm-5;i++)pw[i]=pw[i-1]*27;s[1]=s[n+2]='a'; build(1,n+2,0); n=n+2; rt=(n+1)/2;// } int main() {scanf("%s",s+2); init();scanf("%d",&m);for(int i=1,x,y;i<=m;i++){scanf("%s%d",ch,&x);if(ch[0]=='I')scanf("%s",ch),insert(x,ch[0]);if(ch[0]=='R')scanf("%s",ch),change(x,ch[0]);if(ch[0]=='Q')scanf("%d",&y),printf("%d\n",query(rt,x,y));}return 0; }
转载于:https://www.cnblogs.com/Zinn/p/9724346.html
bzoj 1014 火星人prefix —— splay+hash相关推荐
- BZOJ 1014 火星人prefix
Description 火星人最近研究了一种操作:求一个字串两个后缀的公共前缀.比方说,有这样一个字符串:madamimadam,我们将这个字符串的各个字符予以标号:序号: 1 2 3 4 5 6 7 ...
- 【BZOJ1014】【JSOI2008】火星人prefix Splay处理区间,hash+dichotomy(二分)check出解...
题意不赘述了,太清晰了. 说题解:首先依据原字符串建立SPT.首尾建议多加一个空白字符. 给一个树构图,依照平衡树的前后大小顺序性质能够使它们始终维持为一个序列,而且能够通过rank找到序列的第k个. ...
- 【BZOJ1014】【JSOI2008】火星人prefix Splay处理区间,hash+dichotomy(二分)check出解
题意不赘述了,太清晰了. 说题解:首先根据原字符串建立SPT,首尾建议多加一个空白字符. 给一个树构图,按照平衡树的前后大小顺序性质可以使它们始终维持为一个序列,并且可以通过rank找到序列的第k个. ...
- bzoj 1014: [JSOI2008]火星人prefix(splay维护区间+Hash+二分)
1014: [JSOI2008]火星人prefix Time Limit: 10 Sec Memory Limit: 162 MB Submit: 7588 Solved: 2429 [Submi ...
- splay/fhq-treap 问卷调查反馈—— [JSOI2008]火星人prefix(splay),Strange Queries(fhq-treap)
文章目录 [JSOI2008]火星人prefix Strange Queries [JSOI2008]火星人prefix BZOJ1014 思路很好想,哈希字符串即可 只是平衡树的码量大 注意因为sp ...
- BZOJ1014: [JSOI2008]火星人prefix
BZOJ1014: [JSOI2008]火星人prefix Description 火星人最近研究了一种操作:求一个字串两个后缀的公共前缀. 比方说,有这样一个字符串:madamimadam,我们将这 ...
- [BZOJ 1014][JSOI2008]火星人prefix(Splay+二分+hash)
Description 火星人最近研究了一种操作:求一个字串两个后缀的公共前缀.比方说,有这样一个字符串:madamimadam, 我们将这个字符串的各个字符予以标号:序号: 1 2 3 4 5 6 ...
- 【BZOJ1014】【tyvj3486】火星人prefix,Splay+字符串hash
Time:2016.07.19 Author:xiaoyimi 转载注明出处谢谢 传送门1 传送门2 思路&&注意: LCP这个东西可以用后缀数组,扩展kmp什么的来做 这里加上了插入 ...
- BZOJ 1014 [JSOI2008]火星人prefix
splay维护hash值: 看到大佬们都在打数据结构,我说好的不打数据结构又自己打脸了. 为了写这个昨天还特意去打了Splay的普通平衡树,自从我学会Treap以来第一次用splayA掉普通平衡树QA ...
最新文章
- 学术前沿 | 图像质量量化评估标准综述
- 二、linux最小驱动
- Android Gradle manifestPlaceholders 占位符详解
- 1052 卖个萌 (20 分)
- Laravel核心解读--Session源码解析
- Delphi实现点击按钮触发选择项, 进而实现不同的分支功能
- 《Apache Kafka 实战》读书笔记-认识Apache Kafka
- PKI世界中两个知名的情侣 Alice和Bob
- android 多线程 js,android中的jstack,见见线程都在干嘛
- mysql判断时间是否在某个区间_如何正确理解 RT 并监控 MySQL 的响应时间
- MvvmCross框架在XamarinForms中的使用入门
- csdn积分如何获取攻略
- oracle数据转换,Oracle数据库转换函数
- 信捷PLC之C函数编程(一)
- Windows文件扩展名
- 吉首大学校赛 A	SARS病毒 (欧拉降幂)
- INSTALL_PARSE_FAILED_NO_CERTIFICATES 解决办法
- 计算机基本概念反思,计算机基础教学反思
- Rasa课程、Rasa培训、Rasa面试、Rasa实战系列之Gavin大咖免费公益课程Rasa Paper论文解析核心版
- Python——飞机大战(day10)
热门文章
- python做客户端适合吗_为了选出最合适的 HTTP 客户端,我做了个测评
- 单击托盘显示菜单mfc_PhotoShop制作滚动菜单栏教程
- html5触摸界面设计与开发_原生APP的开发步骤主要分为哪些?
- mysql mssql 性能对比_MySQL最新版8.0与5.7之性能对比,看看它是如何改进的
- collection.stream()以及collect()方法
- 判断浏览器是否支持websocket的方法
- mysql row 格式binlog 恢复_为什么要把MySQL的binlog格式修改为row
- swoole redis
- Linux基础命令之sed用法
- 将Java项目从maven迁移到gradle