BZOJ_1014_[JSOI2008]_火星人prefix_(Splay+LCP_Hash+二分)
描述
http://www.lydsy.com/JudgeOnline/problem.php?id=1014
给出一个字符串,有修改,插入,以及询问LCP(i,j)的操作.
分析
LCP在白书上面有介绍,\(LCP(i,j)\)表示以第\(i\)位和以第\(j\)位开头的后缀的最长公共前缀.
先考虑没有插入和修改操作的问题.我们可以用基于Hash的LCP算法.
我们给每一个后缀一个Hash值.其中以第\(i\)为开头的后缀的Hash值为\(H[i]=H[i+1]x+s[i]\).
其中\(x\)是随便一个什么数.例如:
\(H[4]=s[4]\)
\(H[3]=s[4]x+s[3]\)
\(H[2]=s[4]x^2+s[3]x+s[2]\)
\(H[1]=s[4]x^3+s[3]x^2+s[2]x+s[1]\)
一般地有:
$$H[i]=s[n]x^{n-i}+s[n-1]x^{n-1-i}+...+s[i+1]x+s[i]$$
对于字符串\(s[i]~s[i+L-1]\)(长度为L),定义它的Hash值为:
$$Hash(i,L)=H[i]-H[i+L]x^L$$
其实就是相当于把以\(i\)开头的后缀的Hash值有关\(i+L\)以及后面的部分都砍掉.
当然这个Hash值可以定义为前缀的形式,和后缀的没有区别.
但是注意,并不是字符串不同,Hash值一定不同,只是相同的概率极低,基本可以无视.
至于计算,我们采用unsigned long long ,这样自然溢出相当于对\(2^{64}\)取模.
这样我们就可以判断字串\((i,L)\)与\((j,L)\)是否相等,二分\(L\)的值,取最大可行解即可.
至于修改和插入操作?平衡树来解决咯.平衡树上每个结点的Hash值代表的是以该结点为根的子树代表的字符串的Hash值.
p.s.
1.复习了下Splay,好不熟练啊,还要多练习,不然药丸...
2.调了好久发现是字符串读入的问题...(拍脸)
#include <bits/stdc++.h>
using namespace std; const int maxn=1e5+;
typedef unsigned long long ull;
int n,m;
ull p[maxn];
char s[maxn];
struct Splay{
struct node{
node* c[],* f;
int v,s; ull h;
node(int v,node* t):v(v){ s=;h=v;f=c[]=c[]=t; }
bool d(){ return f->c[]==this; }
void setc(node* x,bool d){ c[d]=x; x->f=this; }
void push_up(){
s=c[]->s+c[]->s+;
h=c[]->h+(ull)v*p[c[]->s]+c[]->h*p[c[]->s+];
}
}* root,* null;
Splay(){
null=new node(,);null->s=;
root=new node(,null); root->setc(new node(,null),);
}
void rot(node* x){
node* f=x->f; bool d=x->d();
f->f->setc(x,f->d());
f->setc(x->c[!d],d);
x->setc(f,!d);
f->push_up();
if(f==root) root=x;
}
void splay(node* x,node *f){
while(x->f!=f)
if(x->f->f==f) rot(x);
else x->d()==x->f->d()?(rot(x->f),rot(x)):(rot(x),rot(x));
x->push_up();
}
node* kth(int k){
for(node* t=root;t!=null;){
int s=t->c[]->s;
if(k==s) return t;
if(k>s) t=t->c[], k-=s+;
else t=t->c[];
}
}
node* get_range(int l,int r){
splay(kth(l-),null);
splay(kth(r+),root);
return root->c[]->c[];
}
void ins(int v,int pos){
node *f=get_range(pos,pos);
f->setc(new node(v,null),); splay(f->c[],null);
}
void chg(int v,int pos){
node *x=get_range(pos,pos);
x->v=v; splay(x,null);
}
int hash(int l,int r){ return get_range(l,r)->h; }
node* build(int l,int r){
if(l>r) return null;
int m=l+(r-l)/;
node *t=new node(s[m]-'a'+,null);
t->setc(build(l,m-),);
t->setc(build(m+,r),);
t->push_up();
return t;
}
}T;
inline int read(int &x){ x=;int k=;char c;for(c=getchar();c<''||c>'';c=getchar())if(c=='-')k=-;for(;c>=''&&c<='';c=getchar())x=x*+c-'';return x*=k; }
inline char read(char &c){ for(c=getchar();(c<'a'||c>'z')&&(c<'A'||c>'Z');c=getchar());return c; }
int bsearch(int x,int y){
int s=T.root->s-;
int l=,r=min(s-x,s-y)+,mid;
while(l<r){
mid=l+(r-l+)/;
if(T.hash(x,x+mid-)==T.hash(y,y+mid-)) l=mid;
else r=mid-;
}
return l;
}
void init(){
scanf("%s",s+); n=strlen(s+); read(m);
p[]=;
for(int i=;i<maxn;i++) p[i]=p[i-]*(ull);
T.root->c[]->setc(T.build(,n),); T.root->c[]->push_up(); T.root->push_up();
}
int main(){
init();
while(m--){
char c; int x,y;
read(c); read(x);
if(c=='Q'){ read(y); printf("%d\n",bsearch(x,y)); }
else if(c=='R') T.chg(read(c)-'a'+,x);
else T.ins(read(c)-'a'+,x);
}
return ;
}
BZOJ_1014_[JSOI2008]_火星人prefix_(Splay+LCP_Hash+二分)的更多相关文章
- 【bzoj1014】[JSOI2008]火星人prefix Splay+Hash+二分
题目描述 火星人最近研究了一种操作:求一个字串两个后缀的公共前缀.比方说,有这样一个字符串:madamimadam,我们将这个字符串的各个字符予以标号:序号: 1 2 3 4 5 6 7 8 9 10 ...
- BZOJ 1014 [JSOI2008]火星人prefix (Splay + Hash + 二分)
1014: [JSOI2008]火星人prefix Time Limit: 10 Sec Memory Limit: 162 MBSubmit: 8112 Solved: 2569[Submit] ...
- P4036 [JSOI2008]火星人(splay+hash+二分)
P4036 [JSOI2008]火星人 Splay维护hash,查询二分 $a[x].vl=a[lc].vl*ha[a[rc].sz+1]+a[x].w*ha[a[rc].sz]+a[rc].vl$ ...
- bzoj1014: [JSOI2008]火星人prefix splay+hash+二分
Description 火星人最近研究了一种操作:求一个字串两个后缀的公共前缀.比方说,有这样一个字符串:madamimadam,我们将这个字符串的各个字符予以标号:序号: 1 2 3 4 5 6 7 ...
- 【BZOJ1014】【JSOI2008】火星人prefix Splay处理区间,hash+dichotomy(二分)check出解
题意不赘述了,太清晰了. 说题解:首先依据原字符串建立SPT.首尾建议多加一个空白字符. 给一个树构图,依照平衡树的前后大小顺序性质能够使它们始终维持为一个序列,而且能够通过rank找到序列的第k个. ...
- BZOJ_1014_[JSOI2008]火星人prefix_splay+hash
BZOJ_1014_[JSOI2008]火星人prefix_splay+hash 题意:火星人最近研究了一种操作:求一个字串两个后缀的公共前缀.比方说,有这样一个字符串:madamimadam, 我们 ...
- 【BZOJ1014】火星人(Splay,哈希)
[BZOJ1014]火星人(Splay,哈希) 题面 BZOJ 题解 要动态维护这个串,一脸的平衡树. 那么用\(Splay\)维护这个哈希值就好了. 每次计算答案的时候二分+Splay计算区间哈希值 ...
- BZOJ_5311_贞鱼_决策单调性+带权二分
BZOJ_5311_贞鱼_决策单调性+带权二分 Description 众所周知,贞鱼是一种高智商水生动物.不过他们到了陆地上智商会减半. 这不?他们遇到了大麻烦! n只贞鱼到陆地上乘车,现在有k辆汽 ...
- [WC2018]即时战略(LCT,splay上二分)
[UOJ题面]http://uoj.ac/problem/349 一道非常好的与数据结构有关的交互题. 首先先看部分分做法, 一上来我们肯定得钦定一个 \(explore\) 的顺序,直接随机就好. ...
随机推荐
- Microsoft Excel Sheet/表格 制作折线图
Microsoft Excel Sheet/表格 制作折线图 虽然比较简单,但是仍然需要稍微花一点功夫. 1.制作好表格数据 2.先将数据选定(不包括 横座标的 年月日或其他的刻度 的那一列) 3.插 ...
- config spec
config_spec Rules for selecting versions of elements to appear in a view APPLICABILITY Product Comma ...
- Less使用——让老司机带你飞
为什么我要使用Less less的作为编写css的工具插件,省时.方便.检测,具体的安装,请参考我的一篇文章<sublime text3 个人使用心得>,里面我讲解了安装方法,使用webs ...
- tomcat错误信息解决方案 严重:StandardServer.await:
看到这个报错我的第一反应就是端口被占用,用netstat -ant命令查看发现8080端口没有被占用,也可以看到 tomcat的进程已经存在,但是不能对外提供服务. 1.独立运行的tomcat.exe ...
- 远程连接Ucenter数据库
网站和Ucenter不是同一服务器的连接方法~我折腾了好几天,终于找到了这方法!各位连接不上的不妨试试~什么事只有试过才知道行不行! define('UC_CONNECT', 'mysql'); de ...
- Pycharm使用技巧
1.代码配色,即主题 pycharm自带的配色方案都很难看,网上的配色方案又很难看,所以根据其他ide的Monokai配色方案,自己定义了一个. pycharm Monokai主题下载:http:// ...
- Python Socket,How to Create Socket Cilent? - 网络编程实例
文章出自:Python socket – network programming tutorial by Silver Moon 原创译文,如有版权问题请联系删除. Network programin ...
- Memcache的部署和使用
一.memcache简介 Memcache是danga.com的一个项目,最早是为 LiveJournal 服务的,目前全世界不少人使用这个缓存项目来构建自己大负载的网站,来分担数据库的压力. Mem ...
- hdu 3303 Harmony Forever (线段树 + 抽屉原理)
http://acm.hdu.edu.cn/showproblem.php?pid=3303 Harmony Forever Time Limit: 20000/10000 MS (Java/Othe ...
- python 程序列表
用 python 通过读取注册表来获取机器安装的程序列表,包括,软件名称,版本号,安装日期等 # -*- coding: UTF8 -*-import _winregimport osimport ...