BZOJ1014:[JSOI2008]火星人(Splay,hash)
Description
火星人最近研究了一种操作:求一个字串两个后缀的公共前缀。比方说,有这样一个字符串:madamimadam,
我们将这个字符串的各个字符予以标号:序号: 1 2 3 4 5 6 7 8 9 10 11 字符 m a d a m i m a d a m 现在,
火星人定义了一个函数LCQ(x, y),表示:该字符串中第x个字符开始的字串,与该字符串中第y个字符开始的字串
,两个字串的公共前缀的长度。比方说,LCQ(1, 7) = 5, LCQ(2, 10) = 1, LCQ(4, 7) = 0 在研究LCQ函数的过程
中,火星人发现了这样的一个关联:如果把该字符串的所有后缀排好序,就可以很快地求出LCQ函数的值;同样,
如果求出了LCQ函数的值,也可以很快地将该字符串的后缀排好序。 尽管火星人聪明地找到了求取LCQ函数的快速
算法,但不甘心认输的地球人又给火星人出了个难题:在求取LCQ函数的同时,还可以改变字符串本身。具体地说
,可以更改字符串中某一个字符的值,也可以在字符串中的某一个位置插入一个字符。地球人想考验一下,在如此
复杂的问题中,火星人是否还能够做到很快地求取LCQ函数的值。
Input
第一行给出初始的字符串。第二行是一个非负整数M,表示操作的个数。接下来的M行,每行描述一个操作。操
作有3种,如下所示
1、询问。语法:Qxy,x,y均为正整数。功能:计算LCQ(x,y)限制:1<=x,y<=当前字符串长度。
2、修改。语法:Rxd,x是正整数,d是字符。功能:将字符串中第x个数修改为字符d。限制:x不超过当前字
符串长度。
3、插入:语法:Ixd,x是非负整数,d是字符。功能:在字符串第x个字符之后插入字符d,如果x=0,则在字
符串开头插入。限制:x不超过当前字符串长度
Output
对于输入文件中每一个询问操作,你都应该输出对应的答案。一个答案一行。
Sample Input
7
Q 1 7
Q 4 8
Q 10 11
R 3 a
Q 1 7
I 10 a
Q 2 11
Sample Output
1
0
2
1
HINT
1、所有字符串自始至终都只有小写字母构成。
2、M<=150,000
3、字符串长度L自始至终都满足L<=100,000
4、询问操作的个数不超过10,000个。
对于第1,2个数据,字符串长度自始至终都不超过1,000
对于第3,4,5个数据,没有插入操作。
Solution
用splay维护hash值
当前点update的时候就用俩儿子的hash值计算一下字符串(左儿子+x+右儿子)新的hash值
hash一开始被卡了素质三连(模数1e4+7不被卡就有鬼了……)
中途有个变量打错了还过了样例emmm……
喜闻乐见样例是有多弱
Code
#include<iostream>
#include<cstring>
#include<cstdio>
#define N (200000+100)
#define MOD (19260817)
using namespace std;
int Val[N],Size[N],Son[N][],Father[N],Sum[N],hash[N];
int Root,n,m,x,y,p,sz;
char opt[],ch[],a[N]; int Get(int x) {return Son[Father[x]][]==x;}
void Clear(int x) {Sum[x]=Father[x]=Son[x][]=Son[x][]=Size[x]=Val[x]=;} void Update(int x)
{
int l=Son[x][],r=Son[x][];
Size[x]=Size[l]+Size[r]+;
Sum[x]=((long long)Sum[l]*hash[Size[r]+]%MOD + (long long)Val[x]*hash[Size[r]+] + Sum[Son[x][]])%MOD;
} void Rotate(int x)
{
int wh=Get(x);
int fa=Father[x],fafa=Father[fa];
Father[fa]=x;
Son[fa][wh]=Son[x][wh^];
if (Son[fa][wh]) Father[Son[fa][wh]]=fa;
Father[x]=fafa;
Son[x][wh^]=fa;
if (fafa) Son[fafa][Son[fafa][]==fa]=x;
Update(fa);
Update(x);
} void Splay(int x,int tar)
{
for (int fa; (fa=Father[x])!=tar; Rotate(x))
if (Father[fa]!=tar)
Rotate(Get(fa)==Get(x)?fa:x);
if (!tar) Root=x;
} int Findx(int x)
{
int now=Root;
while ()
if (Size[Son[now][]]>=x)
now=Son[now][];
else
{
x-=Size[Son[now][]];
if (x==)
{
Splay(now,);
return now;
}
x--;
now=Son[now][];
}
} void Build(int l,int r,int fa)
{
if (l>r) return;
int mid=(l+r)>>;
Build(l,mid-,mid);
Build(mid+,r,mid);
Father[mid]=fa;
Son[fa][mid>fa]=mid;
Val[mid]=a[mid]-'a'+;
Update(mid);
} int Split(int x,int y)
{
int xx=Findx(x),yy=Findx(y);
Splay(xx,);
Splay(yy,xx);
return Son[yy][];
} bool check(int len)
{
int xx=Split(x,x+len+);
int ans1=Sum[xx];
int yy=Split(y,y+len+);
int ans2=Sum[yy];
return ans1==ans2;
} int main()
{
hash[]=;
for (int i=; i<=; ++i)
hash[i]=hash[i-]*%MOD; scanf("%s%d",a+,&m);
n=strlen(a+);
Build(,n+,);
Root=(n+)>>;
sz=n+; for (int i=; i<=m; ++i)
{
scanf("%s",opt);
if (opt[]=='Q')
{
scanf("%d%d",&x,&y);
int l=,r=Size[Root]-max(x,y)-,ans=;
while (l<=r)
if (check((l+r)>>))
{
l=((l+r)>>)+;
ans=l-;
}
else
r=((l+r)>>)-;
printf("%d\n",ans);
}
if (opt[]=='R')
{
scanf("%d%s",&p,ch);
Findx(p+);
Val[Root]=ch[]-'a'+;
Update(Root);
}
if (opt[]=='I')
{
scanf("%d%s",&p,ch);
Split(p+,p+);
int x=Son[Root][];
Val[++sz]=ch[]-'a'+;
Size[sz]=;
Father[sz]=x;
Son[x][]=sz;
Splay(sz,);
}
}
}
BZOJ1014:[JSOI2008]火星人(Splay,hash)的更多相关文章
- [BZOJ1014][JSOI2008]火星人prefix
[BZOJ1014][JSOI2008]火星人prefix 试题描述 火星人最近研究了一种操作:求一个字串两个后缀的公共前缀.比方说,有这样一个字符串:madamimadam,我们将这个字符串的各个字 ...
- BZOJ_1014_[JSOI2008]火星人prefix_splay+hash
BZOJ_1014_[JSOI2008]火星人prefix_splay+hash 题意:火星人最近研究了一种操作:求一个字串两个后缀的公共前缀.比方说,有这样一个字符串:madamimadam, 我们 ...
- BZOJ1014 JSOI2008 火星人prefix 【非旋转Treap】*
BZOJ1014 JSOI2008 火星人prefix Description 火星人最近研究了一种操作:求一个字串两个后缀的公共前缀.比方说,有这样一个字符串:madamimadam,我们将这个字符 ...
- bzoj 1014: [JSOI2008]火星人prefix hash && splay
1014: [JSOI2008]火星人prefix Time Limit: 10 Sec Memory Limit: 162 MBSubmit: 3154 Solved: 948[Submit][ ...
- 2018.06.28 BZOJ1014 [JSOI2008]火星人prefix(非旋treap+hash)
[JSOI2008]火星人prefix Time Limit: 10 Sec Memory Limit: 162 MB Submit: 8951 Solved: 2860 Description 火星 ...
- bzoj千题计划106:bzoj1014 [JSOI2008]火星人prefix
http://www.lydsy.com/JudgeOnline/problem.php?id=1014 两个后缀的最长公共前缀:二分+hash 带修改带插入:splay维护 #include< ...
- bzoj1014: [JSOI2008]火星人prefix splay+hash+二分
Description 火星人最近研究了一种操作:求一个字串两个后缀的公共前缀.比方说,有这样一个字符串:madamimadam,我们将这个字符串的各个字符予以标号:序号: 1 2 3 4 5 6 7 ...
- BZOJ1014[JSOI2008]火星人prefix(splay维护hash)
Description 火星人最近研究了一种操作:求一个字串两个后缀的公共前缀.比方说,有这样一个字符串:madamimadam,我们将这个字符串的各个字符予以标号:序号: 1 2 3 4 5 6 7 ...
- BZOJ1014: [JSOI2008]火星人prefix(splay 二分 hash)
题意 题目链接 Sol 一眼splay + 二分hash,不过区间splay怎么写来着呀 试着写了两个小时发现死活不对 看了一下yyb的代码发现自己根本就不会splay.... // luogu-ju ...
随机推荐
- MySQL---5、可视化工具Navicat for MySQL安装配置
一.安装文件包下载 Navicat for MySQL 安装软件和破解补丁: 链接:https://pan.baidu.com/s/1oKcErok_Ijm0CY9UjNMrnA 密码:4xb1 ...
- MFC—— AfxMessageBox
AfxMessageBox 错误C2665: “AfxMessageBox”: 2 个重载中没有一个可以转换所有参数类型 1,楼主发表于:2007-01-01 03:56:34同样的语句, ...
- java自学-流程控制语句
一件事情从开始到结束,需要先做什么,再做什么,最后再怎么做,这段过程就是一个流程.程序逻辑处理也是一个流程,java中有专门的流程控制语句,主要分为这几种:顺序,判断,选择,循环. 1.顺序流程 顺 ...
- final关键字的特点
1.这个关键字是一个修饰符,可以修饰类,方法,变量. 2.被final修饰的类是一个最终类,不可以被继承. 3.被final修饰的方法是一个最终方法,不可以被覆盖. 4.被final修饰的变量是一个常 ...
- java.sql.SQLException: Io 异常: Invalid number format for port number
java.sql.SQLException: Io 异常: Invalid number format for port number jdbc数据库链接配置没有写端口号 要检查jdbc的配置 ...
- linux ubuntu 安装nginx
参考原文 在Ubuntu下安装Nginx有以下方法,但是如果想要安装最新版本的就必须下载源码包编译安装. 一.基于APT源安装 sudo apt-get install nginx 安装好的文件位置: ...
- docker login 报错 Error response from daemon: Get https://registry-1.docker.io/v2/: unauthorized: incorrect username or password
按照网上说的说法,造成这个现象有很多原因,大家可以多尝试一下,下面贴出解决我问题的方法: docker账户分为两个部分,一个是email,一个是dockerID,使用docker login登陆时要使 ...
- Django框架model实现数据库增删查改
1.创建Django工程 https://www.cnblogs.com/CK85/p/10159159.html 2.在model.py中配置生成表格的类对象. from django.db imp ...
- CF17E Palisection
题意 给定一个长度为n的小写字母串.问你有多少对相交的回文子串(包含也算相交) 相交的回文子串个数 \(mod\ 51123987\) Sol 求相交的回文子串不太好求 考虑用总数减去不相交的回文串个 ...
- Flutter知识点:数据存储之sqflite
sqflite是一款轻量级的关系型数据库,类似SQLite. 在Flutter平台我们使用sqflite库来同时支持Android 和iOS. 使用介绍 1.首选需要在pubspec.yaml 导入库 ...