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+,xm=;
- int n,m,rt,fa[xm],c[xm][],siz[xm];
- ll pw[xm],hsh[xm];
- char s[xn],ch[xn];
- void pushup(int x)
- {
- int ls=c[x][],rs=c[x][];
- siz[x]=siz[ls]+siz[rs]+;
- hsh[x]=hsh[ls]*pw[siz[rs]+]+(s[x]-'a'+)*pw[siz[rs]]+hsh[rs];
- }
- void rotate(int x,int &f)
- {
- int y=fa[x],z=fa[y],d=(c[y][]==x);
- if(z)c[z][c[z][]==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][]==x)^(c[z][]==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'+,siz[l]=;
- else build(l,mid-,mid),build(mid+,r,mid);
- fa[mid]=lst; c[lst][mid>lst]=mid; pushup(mid);
- }
- int find(int x,int k)//找到 k 位置
- {
- while()
- {
- int p=c[x][],q=c[x][];
- if(siz[p]+==k)return x;
- else if(siz[p]+<k)x=q,k-=siz[p]+;
- else x=p;
- }
- }
- void insert(int pos,char d)
- {
- s[++n]=d; hsh[n]=d-'a'+;
- int x=find(rt,pos+);//+1 因为有左右的'a'
- splay(x,); x=find(rt,pos+); splay(x,rt);//
- // splay(x,rt); x=find(rt,pos+2); splay(x,c[rt][1]);
- c[x][]=n; siz[n]=; fa[n]=x;
- pushup(x); pushup(rt);
- }
- void change(int pos,char d)
- {
- int x=find(rt,pos+);
- splay(x,);//
- // splay(x,rt);
- s[x]=d; pushup(x);
- }
- bool ck(int l,int r,int k)
- {
- ll h1=,h2=;
- // 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,);
- x=find(rt,l+k+); splay(x,rt);
- h1=hsh[c[x][]];
- // 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,);
- x=find(rt,r+k+); splay(x,rt);
- h2=hsh[c[x][]];
- return h1==h2;
- }
- int query(int x,int l,int r)
- {
- int ll=,rr=n--max(l,r)+,ret=;
- while(ll<=rr)
- {
- int md=((ll+rr)>>);
- if(ck(l,r,md))ret=md,ll=md+;
- else rr=md-;
- }
- return ret;
- }
- void init()
- {
- n=strlen(s+); pw[]=;
- for(int i=;i<=xm-;i++)pw[i]=pw[i-]*;
- s[]=s[n+]='a';
- build(,n+,); n=n+; rt=(n+)/;//
- }
- int main()
- {
- scanf("%s",s+); init();
- scanf("%d",&m);
- for(int i=,x,y;i<=m;i++)
- {
- scanf("%s%d",ch,&x);
- if(ch[]=='I')scanf("%s",ch),insert(x,ch[]);
- if(ch[]=='R')scanf("%s",ch),change(x,ch[]);
- if(ch[]=='Q')scanf("%d",&y),printf("%d\n",query(rt,x,y));
- }
- return ;
- }
bzoj 1014 火星人prefix —— splay+hash的更多相关文章
- BZOJ 1014: [JSOI2008]火星人prefix( splay + hash )
用splay维护序列, 二分+hash来判断LCQ.. #include<bits/stdc++.h> using namespace std; typedef unsigned long ...
- BZOJ 1014 [JSOI2008]火星人prefix (Splay + Hash + 二分)
1014: [JSOI2008]火星人prefix Time Limit: 10 Sec Memory Limit: 162 MBSubmit: 8112 Solved: 2569[Submit] ...
- 【BZOJ1014】[JSOI2008]火星人prefix Splay+hash
[BZOJ1014][JSOI2008]火星人prefix Description 火星人最近研究了一种操作:求一个字串两个后缀的公共前缀.比方说,有这样一个字符串:madamimadam,我们将这个 ...
- 【bzoj1014】[JSOI2008]火星人prefix Splay+Hash+二分
题目描述 火星人最近研究了一种操作:求一个字串两个后缀的公共前缀.比方说,有这样一个字符串:madamimadam,我们将这个字符串的各个字符予以标号:序号: 1 2 3 4 5 6 7 8 9 10 ...
- $bzoj1014-JSOI2008$ 火星人$prefix$ $splay$ $hash$
题面描述 火星人最近研究了一种操作:求一个字串两个后缀的公共前缀.比方说,有这样一个字符串:\(madamimadam\),我们将这个字符串的各个字符予以标号: 序号 1 2 3 4 5 6 7 8 ...
- 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 - 链表 - 分块
Description 火星人最近研究了一种操作:求一个字串两个后缀的公共前缀.比方说,有这样一个字符串:madamimadam,我们将这个字符串的各个字符予以标号:序号: 1 2 3 4 5 6 7 ...
- bzoj1014: [JSOI2008]火星人prefix splay+hash+二分
Description 火星人最近研究了一种操作:求一个字串两个后缀的公共前缀.比方说,有这样一个字符串:madamimadam,我们将这个字符串的各个字符予以标号:序号: 1 2 3 4 5 6 7 ...
随机推荐
- hdu 1496 hash
hash?判重,是否一样?相等?等式!没有想到,这次题做玩后,学到了HASH这一功能!当数据量在数组允许大小范围内时候即可!判断等式俩边是否相等,从而获得解的个数!从复杂度,n*m*k****,降到 ...
- Delphi:解决重绘造成的窗体闪烁问题
解决窗体闪烁问题 具体代码: 1.在声明窗体类时加入: private procedure CreateParams(var Params: TCreateParams); overrid ...
- Python高级进阶(二)Python框架之Django写图书管理系统(LMS)
正式写项目准备前的工作 Django是一个Web框架,我们使用它就是因为它能够把前后端解耦合而且能够与数据库建立ORM,这样,一个Python开发工程师只需要干自己开发的事情就可以了,而在使用之前就我 ...
- java Map集合对比分析
1.Map:Map是所有map集合的顶级父接口,用于key/value形式的键值对,其中每一个key都映射到一个值,key不能重复. 2.TreeMap:该map将存储的键值对进行默认排序,并且还能够 ...
- 在SUSE12中使用 Machinery 进行高级系统管理
简单介绍 在 SUSE Linux Enterprise 12 中.SUSE 如今推出了面向系统管理员的 Machinery.作为其高级系统管理模块的一部分.Machinery 是适用于 Linux ...
- [TypeScript] Query Properties with keyof and Lookup Types in TypeScript
The keyof operator produces a union type of all known, public property names of a given type. You ca ...
- HTC 328T 提示手机存储不足 out of space怎么办
不要再用什么软件做优化,做清理,都是治标不治本啊. 1 用豌豆荚备份数据 2 手机恢复出厂设置 3 用豌豆荚恢复数据
- 我的第一个开源控件-DragGridView
我的第一个开源控件出炉了,希望各个小伙伴给个star,支持下.项目地址 1. 前言 因为项目须要,要做一个相似腾讯视频.频道管理.拖拽排序的效果.这个控件是在原地址 之上改造出来的.先看下效果图. 1 ...
- MVC架构在游戏开发中的应用
一 定义 MVC即Model View Controller,是模型(model)-视图(view)-控制器(controller)的缩写. MVC是一种"前端"的设计模式. MV ...
- RabbitMQ常用命令、管理界面
1.运行CMD,cd切换到RabbitMQ安装目录sbin下E:\Program Files\RabbitMQ Server\rabbitmq_server-3.7.2\sbin 执行 rabbitm ...