【bzoj1014】[JSOI2008]火星人prefix
1014: [JSOI2008]火星人prefix
Time Limit: 10 Sec Memory Limit: 162 MB
Submit: 6031 Solved: 1917
[Submit][Status][Discuss]
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个数据,没有插入操作。
【题解】
用splay维护字符串,把一段子串用哈希值表示,两个长度相同的子串如果哈希值相同,那么它们就相同。
建树时每棵子树的哈希值集中在根节点上,即h[x]=(h[left[x]]+v[x]*p[size[left]]+h[r]*p[size[left]+1])%mod
查询时二分一个答案,然后验证。
那么如何找到子串的哈希值呢?
首先找到子串的首字母,把它伸展到根,然后找到子串的尾字母的下一个字母,把它伸展到根的右儿子,那么根的右儿子的左儿子的哈希值就是答案。
吐槽:这题交了很多遍,都是RE,然后我才知道BZOJ上用cin会RE......
#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<cmath>
#include<ctime>
#include<algorithm>
using namespace std;
#define MAXN 150010
#define ll long long
#define mod 9875321
int n,m,rt,sz,p[MAXN],c[MAXN][],fa[MAXN],size[MAXN],h[MAXN],v[MAXN];
char ch[MAXN];
namespace INIT
{
inline int read()
{
int x=,f=; char ch=getchar();
while(!isdigit(ch)) {if(ch=='-') f=-; ch=getchar();}
while(isdigit(ch)) {x=x*+ch-''; ch=getchar();}
return x*f;
}
}using namespace INIT;
namespace SPLAY
{
void updata(int x)
{
int l=c[x][],r=c[x][];
size[x]=size[l]+size[r]+;
h[x]=h[l]+(ll)v[x]*p[size[l]]%mod+(ll)p[size[l]+]*h[r]%mod;
h[x]%=mod;
}
void rotate(int x,int &k)
{
int y=fa[x],z=fa[y],l,r;
if(c[y][]==x) l=; else l=; r=l^;
if(y==k) k=x;
else {if(c[z][]==y) c[z][]=x; else c[z][]=x;}
fa[x]=z; fa[y]=x; fa[c[x][r]]=y;
c[y][l]=c[x][r]; c[x][r]=y;
updata(y); updata(x);
}
void Splay(int x,int &k)
{
while(x!=k)
{
int y=fa[x],z=fa[y];
if(y!=k)
{
if((c[y][]==x)^(c[z][]==y)) rotate(x,k);
else rotate(y,k);
}
rotate(x,k);
}
}
void build(int k,int l,int r)
{
if(l>r) return;
if(l==r)
{
v[l]=h[l]=ch[l]-'a'+;
fa[l]=k; size[l]=;
if(l<k) c[k][]=l;
else c[k][]=l;
return;
}
int mid=(l+r)/;
build(mid,l,mid-); build(mid,mid+,r);
v[mid]=ch[mid]-'a'+; fa[mid]=k; updata(mid);
if(mid<k) c[k][]=mid;
else c[k][]=mid;
}
int find(int k,int rank)
{
int l=c[k][],r=c[k][];
if(size[l]+==rank) return k;
else if(size[l]>=rank) return find(l,rank);
else return find(r,rank-size[l]-);
}
int check(int k,int val)
{
int x=find(rt,k),y=find(rt,k+val+);
Splay(x,rt); Splay(y,c[x][]);
int z=c[y][];
return h[z];
}
int ask(int x,int y)
{
int l=,r=min(sz-x,sz-y)-,ans=;
while(l<=r)
{
int mid=(l+r)/;
if(check(x,mid)==check(y,mid)) {l=mid+; ans=mid;}
else r=mid-;
}
return ans;
}
void insert(int k,int val)
{
int x=find(rt,k+),y=find(rt,k+);
Splay(x,rt); Splay(y,c[x][]);
int z=++sz; c[y][]=z; fa[z]=y; v[z]=val;
updata(z); updata(y); updata(x);
}
}using namespace SPLAY;
int main()
{
//freopen("cin.in","r",stdin);
//freopen("cout.out","w",stdout);
scanf("%s",ch+);
n=strlen(ch+); p[]=;
for(int i=;i<=MAXN;i++) p[i]=p[i-]*%mod;
build(,,n+); rt=(n+)/; sz=n+;
m=read(); int x,y;
char s[],d[];
for(int i=;i<=m;i++)
{
scanf("%s",s+); x=read();
if(s[]=='Q') {y=read(); printf("%d\n",ask(x,y));}
if(s[]=='R') {scanf("%s",d+); x=find(rt,x+); Splay(x,rt); v[rt]=d[]-'a'+; updata(rt);}
if(s[]=='I') {scanf("%s",d+); insert(x,d[]-'a'+);}
}
return ;
}
附makedata程序(博主很良心,知道你会wa):
#include<iostream>
using namespace std;
char ch[]={'Q','R','I'};
int main()
{
freopen("cin.in","w",stdout);
srand(time(NULL));
int n=;
for(int i=;i<=n;i++) printf("%c",(char)('a'+rand()%));
printf("\n");
int m=;
printf("%d\n",m);
for(int i=;i<=m;i++)
{
char f=ch[rand()%];
if(f=='Q') {printf("%c %d %d\n",f,rand()%n+,rand()%n+);}
if(f=='R') {printf("%c %d %c\n",f,rand()%n+,(char)('a'+rand()%));}
if(f=='I') {printf("%c %d %c\n",f,rand()%n+,(char)('a'+rand()%));}
}
return ;
}
【bzoj1014】[JSOI2008]火星人prefix的更多相关文章
- [BZOJ1014][JSOI2008]火星人prefix
[BZOJ1014][JSOI2008]火星人prefix 试题描述 火星人最近研究了一种操作:求一个字串两个后缀的公共前缀.比方说,有这样一个字符串:madamimadam,我们将这个字符串的各个字 ...
- BZOJ1014 JSOI2008 火星人prefix 【非旋转Treap】*
BZOJ1014 JSOI2008 火星人prefix Description 火星人最近研究了一种操作:求一个字串两个后缀的公共前缀.比方说,有这样一个字符串:madamimadam,我们将这个字符 ...
- 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 & 二分答案)
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维护哈希)
Description 火星人最近研究了一种操作:求一个字串两个后缀的公共前缀. 比方说,有这样一个字符串:madamimadam,我们将这个字符串的各个字符予以标号:序号: 1 2 3 4 5 6 ...
- 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 ...
- bzoj1014: [JSOI2008]火星人prefix(splay+hash+二分)
题目大意:一个字符串三个操作:①求两个后缀的LCP②插入一个字符③修改一个字符. 前几天刚学了hash+二分求lcp,就看到这题. 原来splay还能这么用?!原来splay模板这么好写?我以前写的s ...
随机推荐
- 【漫画解读】HDFS存储原理(转载)
以简洁易懂的漫画形式讲解HDFS存储机制与运行原理. 一.角色出演 如上图所示,HDFS存储相关角色与功能如下: Client:客户端,系统使用者,调用HDFS API操作文件;与NN交互获取文件元数 ...
- mysql实体关系(mysql学习五)
实体关系 表设计 1:1 两个实体表内,存在相同的主键字段 如果记录的主键值等于另一个关系表内记录的主键值,则两条记录的对应为一一对应 优化上称为垂直分割 1:n 一个实体对应多个其他实体(一个班级 ...
- php常用函数集锦[备份用的]
1.判断是否正确的日期格式 /** * 是否正确的日期 * * @access public */ private function _isdate($str,$format="Y-m-d ...
- PHP-You don’t have permissions to access xxx on this server!
问题如下图: 如果你是想要查看目录下的每一个文件,那么你需要修改一下httpd-conf配置文件,也就是apache的配置文件,以phpStudy2013为例,如下图打开: 然后找到如下部分,添加 ...
- Vmware下Ubuntu无法上网的问题
本来这个挺简单的个问题,但是由于很久没有使用虚拟机并且期间实体机网络环境发生了一些变化,导致了一些麻烦. 一般用NAT就行了,就是Vmware右下角那个图标(左起第4个)设置就行. 我这么设置了还是不 ...
- 配置visual studio code进行asp.net core rc2的开发(转载jeffreywu)
1.安装.net core sdk https://github.com/dotnet/cli#installers-and-binaries,根据你的系统选择下载 2.下载vscode的C#扩展插件 ...
- bat完美关机命令
@echo off title OLIVER-COMPUTER mode con cols= lines= color 0d shutdown /a >nul >nul ver > ...
- Oracle ClusterwarePRCT-1011 : Failed to run "oifcfg".&nb
OS: Oracle Linux Server release 6.3 DB: Oracle 11.2.0.3 在oracle-linux6.3安装11g RAC,在安装软件时候提示: An inte ...
- 源码解析之setContentView
分享一下我以前学习时做到PPT中的一部分. 不难看出其实设置布局是由PhoneWindow来完成的. 然而我们要记住DecorView: 包括:状态栏,标题栏,内容 phoneWindow -> ...
- Zygote(app_process)相关分析2
在前一篇文章中已经分析了从init.c到Zygote(app_process)的启动流程. 今天开始分析frameworks/base/cmds/app_process/app_main.cpp. s ...