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 ...
随机推荐
- Codeforces603E - Pastoral Oddities
Portal Description 初始时有\(n(n\leq10^5)\)个孤立的点,依次向图中加入\(m(m\leq3\times10^5)\)条带权无向边.使得图中每个点的度数均为奇数的边集是 ...
- 删除字符串中的"\U0000fffc"数据 textView添加图片 以及添加后属性失效的解决
背景:在实现textView的富文本时,如果添加一张图片后,如果直接发送textView的内容时,图片会被字符串“\U0000fffc”替换. 问题:如何删除“\U0000fffc”字符串:如何替换t ...
- POJ 1511 【heap+dij】
题意: t组样例. 每组有n个节点,有m条单向边. 有m组输入,每组a b c 表示从a到b的单向边的权值是c. 求解,从编号为1的节点出发,有n-1个人,要求他们分别到达编号从2到n的节点再返回,所 ...
- 下载数据到Excel,工具类
使用反射将model数据下载到Excel中 package test.upload.utils; import java.lang.reflect.Method; import java.math.B ...
- window环境下搭建SVN服务器
<span style="font-family: Arial; rgb(255, 255, 255);">第一步:准备工具:</span> 1.SVN服务 ...
- 报错** is not accessible due to restriction on required library
报错: Description Resource Path Location TypeAccess restriction: The type Map<String,Object> is ...
- MySQL基础笔记(三) 复杂查询
所谓复杂查询,指涉及多个表.具有嵌套等复杂结构的查询.这里简要介绍典型的几种复杂查询格式. 一.连接查询 连接是区别关系与非关系系统的最重要的标志.通过连接运算符可以实现多个表查询.连接查询主要包括内 ...
- 模仿猫眼电影App一个动画效果
看真正的猫眼效果图 watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvdTAxMzIxMDYyMA==/font/5a6L5L2T/fontsize/400/f ...
- 在Oracle数据库中使用NFS,怎样调优?
MOS上有好多文章,基本上都跑不了以下三点: Setup can make a big difference 1. Network topology and load 2. NFS mount opt ...
- iOS视频流开发(2) — 视频播放
iOS视频流开发(2) — 视频播放 承上篇,本篇文章主要介绍iOS视频播放需要用到的类.以及他们的使用场景和开发中遇到的问题. MPMoviePlayerViewController MP简介 i ...