[JSOI2008]火星人prefix

Time Limit: 10 Sec Memory Limit: 162 MB

Submit: 8951 Solved: 2860

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

madamimadam

7

Q 1 7

Q 4 8

Q 10 11

R 3 a

Q 1 7

I 10 a

Q 2 11

Sample Output

5

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个数据,没有插入操作。

题意简述:维护一个字符串中任意两段后缀的最长前缀,支持修改和插入操作。

我们先来思考一下静态版本,如果让我们维护字符串中任意两段后缀的最长前缀,怎么做?后缀数组?

其实我们可以用更简单的二分+哈希的方法来替代,尽管二分+哈希的效率不如前者优秀,但是码量少,思维难度小,并且实际测试并不慢。

动态版本?

但当我们看到插入操作时,不难联想到这是一道平衡树的题目,怎么维护?

如果我们按每个字符在序列中的位置为序建立这棵平衡树来维护区间的哈希值的话,每次只需提取出(ql,n)(ql,n)(ql,n)和(qr,n)(qr,n)(qr,n)来二分答案即可。

代码如下

#include<bits/stdc++.h>
#define M 1000010
#define bas 37
using namespace std;
typedef pair<int,int> res;
unsigned int hash[M],po[M];
int q,son[M][2],siz[M],v[M],rd[M],tot=0,root=0;
inline void pushup(int p){
	siz[p]=siz[son[p][0]]+siz[son[p][1]]+1;
	hash[p]=hash[son[p][0]]+v[p]*po[siz[son[p][0]]]+hash[son[p][1]]*po[siz[son[p][0]]+1];
}
inline int merge(int a,int b){
	if(!a||!b)return a+b;
	if(rd[a]<rd[b]){son[a][1]=merge(son[a][1],b),pushup(a);return a;}
	son[b][0]=merge(a,son[b][0]),pushup(b);return b;
}
inline res split(int a,int k){
	if(!a)return res(0,0);
	res ans,tmp;
	if(siz[son[a][0]]>=k){
		tmp=split(son[a][0],k);
		son[a][0]=tmp.second,pushup(a);
		ans.first=tmp.first,ans.second=a;
		return ans;
	}
	tmp=split(son[a][1],k-siz[son[a][0]]-1);
	son[a][1]=tmp.first,pushup(a);
	ans.first=a,ans.second=tmp.second;
	return ans;
}
inline int build(int val){
	int ret=++tot;
	hash[tot]=v[tot]=val;
	son[tot][0]=son[tot][1]=0;
	rd[tot]=rand();
	siz[tot]=1;
	return tot;
}
inline void insert(int pos,int v){
	res tmp=split(root,pos);
	int p=build(v);
	root=merge(merge(tmp.first,p),tmp.second);
}
inline void erase(int pos){
	res x=split(root,pos);
	res y=split(x.first,pos-1);
	root=merge(y.first,x.second);
}
char s[150005];
inline int ask(int p,int len){
	if(p+len-1>siz[root])return -1;
	res x=split(root,p-1);
	res y=split(x.second,len);
	int ret=hash[y.first];
	root=merge(x.first,merge(y.first,y.second));
	return ret;
}
inline void query(int ql,int qr){
	int l=0,r=siz[root]-qr+1,ans=0;
	while(l<=r){
		int mid=l+r>>1;
		int ax=ask(ql,mid),ay=ask(qr,mid);
		if(ax==-1||ay==-1){r=mid-1;continue;}
		if(ax==ay)ans=mid,l=mid+1;
		else r=mid-1;
	}
	printf("%d\n",ans);
}
int main(){
	po[0]=1;
	for(int i=1;i<=100000;++i)po[i]=po[i-1]*bas;
	scanf("%s",s+1);
	int len=strlen(s+1),l,r;
	for(int i=1;i<=len;++i)root=merge(root,build(s[i]-'a'));
	scanf("%d",&q);
	while(q--){
		char op[3],c[3];
		scanf("%s",op);
		if(op[0]=='Q'){
			scanf("%d%d",&l,&r);
			query(l,r);
		}
		if(op[0]=='R'){
			scanf("%d%s",&l,c);
			erase(l);
			insert(l-1,c[0]-'a');
		}
		if(op[0]=='I'){
			scanf("%d%s",&l,&c);
			insert(l,c[0]-'a');
		}
	}
	return 0;
}

2018.06.28 BZOJ1014 [JSOI2008]火星人prefix(非旋treap+hash)的更多相关文章

  1. [Bzoj1014][JSOI2008]火星人prefix(无旋Treap&hash)

    题目链接:https://www.lydsy.com/JudgeOnline/problem.php?id=1014 因为涉及到增加和修改,所以后缀数组就被pass掉了,想到的就是平衡树维护hash值 ...

  2. BZOJ1014 JSOI2008 火星人prefix 【非旋转Treap】*

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

  3. [BZOJ1014][JSOI2008]火星人prefix

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

  4. bzoj千题计划106:bzoj1014 [JSOI2008]火星人prefix

    http://www.lydsy.com/JudgeOnline/problem.php?id=1014 两个后缀的最长公共前缀:二分+hash 带修改带插入:splay维护 #include< ...

  5. Jewel Magic UVA - 11996 || bzoj1014: [JSOI2008]火星人prefix

    Jewel Magic UVA - 11996 这是一道用splay/非旋treap做的题(这里用的是非旋treap) 1/2/3是splay/非旋treap的常规操作.对于操作4,可以用哈希法求LC ...

  6. 2018.08.06 bzoj1500: [NOI2005]维修数列(非旋treap)

    传送门 平衡树好题. 我仍然是用的fhqtreap,感觉速度还行. 维护也比线段树splay什么的写起来简单. %%%非旋treap大法好. 代码: #include<bits/stdc++.h ...

  7. [bzoj1014][JSOI2008]火星人prefix_非旋转Treap_hash_二分

    火星人prefix bzoj-1014 JSOI-2004 题目大意:给定一个字符串,支持三种操作:1.查询:两个后缀之间的$LCP$:2.单点修改:3.插入一个字符. 注释:$1\le n\le 1 ...

  8. [BZOJ1014] [JSOI2008] 火星人prefix (splay & 二分答案)

    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. mysql 集群 数据同步

    mysql集群配置在网站负载均衡中是必不可少的: 首先说下我个人准备的负载均衡方式: 1.通过nginx方向代理来将服务器压力分散到各个服务器上: 2.每个服务器中代码逻辑一样: 3.通过使用redi ...

  2. Delphi XE6打电话

    procedure TPhoneDialerForm.btnMakeCallClick(Sender: TObject); var PhoneDialerService: IFMXPhoneDiale ...

  3. 更新403 Forbidden

    用TidHTTP下载一个文件 http://192.168.1.1/files/新建文本文档.txt 报错,但是用浏览器打开正常 HTTP/1.1 403 Forbidden 最后不是程序的问题,把i ...

  4. eclipse Jsp 自创建tags问题

    Can not find the tag directory "/WEB-INF/tags" 网上的说法有三种情况: 1. jsp2.0开始支持自定义tag,因此 web.xml文 ...

  5. JS、CSS以及img对DOMContentLoaded事件的影响

    最近在做性能有关的数据上报,发现了两个非常有意思的东西:Chrome开发者工具的Timeline分析面板,以及DOMContentLoaded事件.一个是强大的令人发指的性能分析工具,一个是重要的性能 ...

  6. 遍历Datatable

    //方法一 DataSet dataSet = new DataSet(); DataTable dt = dataSet.Tables[]; ; i < dt.Rows.Count; i++) ...

  7. spring cloud: eureka搭建

    1. 添加pom 依赖: <parent> <groupId>org.springframework.boot</groupId> <artifactId&g ...

  8. 编写jQuery插件(二)——jQuery插件类型和机制

    jQuery插件类型 jQuery插件主要有3种类型: 1.封装对象方法的插件 这种插件类型是最常见的一种插件,它将对象方法封装起来,对通过选择器获取的jQuery对象进行操作. 2.封装全局函数的插 ...

  9. Spring MVC 接受的请求参数

    目录 1. 概述 2. 详解 2.1 处理查询参数 2.2 处理路径参数接受输入 2.3 处理表单 3. 补充内容 3.1 Ajax/JSON 输入 3.2 multipart参数 3.3 接收 he ...

  10. Spring的国际化(转载)

    1:在MyEclipse下面创建一个test的Web  Project,然后添加Spring相关的文件,在src根目录下创建applicationContext.xml文件. applicationC ...