题目: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的更多相关文章

  1. BZOJ 1014: [JSOI2008]火星人prefix( splay + hash )

    用splay维护序列, 二分+hash来判断LCQ.. #include<bits/stdc++.h> using namespace std; typedef unsigned long ...

  2. BZOJ 1014 [JSOI2008]火星人prefix (Splay + Hash + 二分)

    1014: [JSOI2008]火星人prefix Time Limit: 10 Sec  Memory Limit: 162 MBSubmit: 8112  Solved: 2569[Submit] ...

  3. 【BZOJ1014】[JSOI2008]火星人prefix Splay+hash

    [BZOJ1014][JSOI2008]火星人prefix Description 火星人最近研究了一种操作:求一个字串两个后缀的公共前缀.比方说,有这样一个字符串:madamimadam,我们将这个 ...

  4. 【bzoj1014】[JSOI2008]火星人prefix Splay+Hash+二分

    题目描述 火星人最近研究了一种操作:求一个字串两个后缀的公共前缀.比方说,有这样一个字符串:madamimadam,我们将这个字符串的各个字符予以标号:序号: 1 2 3 4 5 6 7 8 9 10 ...

  5. $bzoj1014-JSOI2008$ 火星人$prefix$ $splay$ $hash$

    题面描述 火星人最近研究了一种操作:求一个字串两个后缀的公共前缀.比方说,有这样一个字符串:\(madamimadam\),我们将这个字符串的各个字符予以标号: 序号 1 2 3 4 5 6 7 8 ...

  6. BZOJ 1014 火星人prefix

    Description 火星人最近研究了一种操作:求一个字串两个后缀的公共前缀.比方说,有这样一个字符串:madamimadam,我们将这个字符串的各个字符予以标号:序号: 1 2 3 4 5 6 7 ...

  7. [BZOJ]1014 火星人prefix(JSOI2008)

    一边听省队dalao讲课一边做题真TM刺激. BZOJ的discuss简直就是题面plus.大样例.SuperHINT.dalao题解的结合体. Description 火星人最近研究了一种操作:求一 ...

  8. bzoj 1014 火星人prefix - 链表 - 分块

    Description 火星人最近研究了一种操作:求一个字串两个后缀的公共前缀.比方说,有这样一个字符串:madamimadam,我们将这个字符串的各个字符予以标号:序号: 1 2 3 4 5 6 7 ...

  9. bzoj1014: [JSOI2008]火星人prefix splay+hash+二分

    Description 火星人最近研究了一种操作:求一个字串两个后缀的公共前缀.比方说,有这样一个字符串:madamimadam,我们将这个字符串的各个字符予以标号:序号: 1 2 3 4 5 6 7 ...

随机推荐

  1. Python基础教程笔记——第5章:条件,循环和其他语句

    5.1 print和import的更多信息 1. print()3.0之后print不再是语句,而是函数, >>> print('udg',12,13)   udg 12 13 &g ...

  2. linux命令1——基础

    Rm 删除命令 Rm [选项][文件] 删除一个文件或者目录 选项:r 递归的删除文件夹及其子文件,f 忽略不存在的文件(不提示) (2)rm删除目录下所有文件,但不删除目录 >>rm - ...

  3. js面试题总结

    1.typeof和Object.prototype.toString typeof是js里面判断变量类型的一种方法,但这种方法没有Object.prototype.toString准确,前者有6种判断 ...

  4. 洛谷 P4720 【模板】扩展 / 卢卡斯 模板题

    扩展卢卡斯定理 : https://www.luogu.org/problemnew/show/P4720 卢卡斯定理:https://www.luogu.org/problemnew/show/P3 ...

  5. Palindrome--poj 1159(最长公共子字符串+滚动数字)

    http://poj.org/problem?id=1159 题目大意:  给你一个n  代表n个字符   第二行给你一个字符串  求使这个字符串变成回文字符串 最少需要添加多少个字符 分析:   原 ...

  6. Partition List(链表的插入和删除操作,找前驱节点)

    Given a linked list and a value x, partition it such that all nodes less than x come before nodes gr ...

  7. Spring MVC静态资源实例

    以下内容引用自http://wiki.jikexueyuan.com/project/spring/mvc-framework/spring-static-pages-example.html: 例子 ...

  8. Eclipse通过Maven构建时出现: Fatal error compiling: tools.jar not found: Fatal error compiling: tools.jar not found: C:\Program Files\Java\jre1.8.0_31\..\lib\tools.jar

    错误: Failed to execute goal org.apache.maven.plugins:maven-compiler-plugin:2.5.1:compile (default-com ...

  9. Jinja2如何默认将None 值显示为空字符串?

    在Jinja模板中 {% if User %} {{ User.name }} {% endif %} 可以简化为下面的写法,同时,保证返回值为空,而不是显示为“None” {{ User.name ...

  10. paramiko连接sshd使用的hostkey

    1.sshd的hostkey设置: cat /etc/ssh/sshd_config 里面有rsa/dsa/ecdsa/ed25519 2.查看paramiko的keys选择顺序,如图所示 3.由以上 ...