【题目链接】

http://www.lydsy.com/JudgeOnline/problem.php?id=1014

【题意】

给定一个字符串,要求提供修改一个字符,插入一个字符,查询两个后缀LCP的功能。

【思路】

  splay维护字符串的哈希值。因为要提供区间,splay采用先查找后调整至根的写法。

一个结点的hash值为:

ch[0]->h * X^(ch[1]->s+1)+v * X^(ch[1]->s)+ch[1]->h

    对于一个询问每次二分长度,提取区间后比较hash值即可。

需要注意的是splay要提前在区间的左右两边各加上一个节点,不然会调用到null。

ull自然溢出相当于模2^64。

【代码】

 #include<set>
#include<cmath>
#include<queue>
#include<vector>
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
#define trav(u,i) for(int i=front[u];i;i=e[i].nxt)
#define FOR(a,b,c) for(int a=(b);a<=(c);a++)
using namespace std; typedef long long ll;
typedef unsigned long long ull;
const int N = 5e5+;
const int X = ; ll read() {
char c=getchar();
ll f=,x=;
while(!isdigit(c)) {
if(c=='-') f=-; c=getchar();
}
while(isdigit(c))
x=x*+c-'',c=getchar();
return x*f;
} char s[N];
int n,q;
ull powx[N]; struct Node* null;
struct Node {
int s,v; ull h;
Node* ch[];
int cmp(int k) {
if(k==ch[]->s+) return -;
return k<=ch[]->s? :;
}
void init(int x) {
v=h=x; s=;
ch[]=ch[]=null;
}
void maintain() {
s=ch[]->s+ch[]->s+;
h=ch[]->h*powx[ch[]->s+]+v*powx[ch[]->s]+ch[]->h;
}
} *root,nodepool[N]; int nodesz=; void rot(Node* &o,int d) {
Node* k=o->ch[d^]; o->ch[d^]=k->ch[d]; k->ch[d]=o;
o->maintain(),k->maintain(); o=k;
}
void splay(Node*& o,int k) {
int d=o->cmp(k);
if(d==) k-=o->ch[]->s+;
if(d!=-) {
Node* p=o->ch[d];
int d2=p->cmp(k),k2=(d2==?k:k-p->ch[]->s-);
if(d2!=-) {
splay(p->ch[d2],k2);
if(d==d2) rot(o,d^); else rot(o->ch[d],d);
}
rot(o,d^);
}
}
//return range (l,r]
//加过点后 s[l,r]=range(l,r+1)
Node*& range(int l,int r) {
splay(root,l);
splay(root->ch[],r-l+);
return root->ch[]->ch[];
} Node* build(int l,int r)
{
if(r<l) return null;
int mid=l+r>>;
Node* o=&nodepool[++nodesz];
o->init(s[mid]-'a'+);
o->ch[]=build(l,mid-);
o->ch[]=build(mid+,r);
o->maintain();
return o;
}
void insert(int p,int v)
{
splay(root,p+);
Node* o=&nodepool[++nodesz];
o->init(v);
o->ch[]=root->ch[]; o->ch[]=null;
o->maintain();
root->ch[]=o; root->maintain();
}
void change(int p,int v)
{
splay(root,p);
root->v=v;
root->maintain();
} int main()
{
//freopen("in.in","r",stdin);
//freopen("out.out","w",stdout);
null=new Node();
scanf("%s",s+);
int n=strlen(s+);
s[]='z'+; s[++n]='z'+; s[n+]='\0';
scanf("%d",&q);
powx[]=;
FOR(i,,n+q) powx[i]=powx[i-]*X;
root=build(,n);
while(q--) {
char op[],val[];
int x,y;
scanf("%s%d",op,&x);
if(op[]=='R') {
scanf("%s",val);
change(x+,val[]-'a'+);
} else
if(op[]=='I') {
scanf("%s",val);
insert(x+,val[]-'a'+);
} else {
scanf("%d",&y);
int len=root->s,L=,R=;
R=min(len-y-,len-x-);
while(L<R) {
int M=L+(R-L+)/;
ull H=range(x,x+M)->h;
H-=range(y,y+M)->h;
if(!H) L=M; else R=M-;
}
printf("%d\n",L);
} }
return ;
}

bzoj 1014 [JSOI2008]火星人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. BZOJ 1014: [JSOI2008]火星人prefix [splay 二分+hash] 【未完】

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

  4. BZOJ 1014: [JSOI2008]火星人prefix Splay+二分

    1014: [JSOI2008]火星人prefix 题目连接: http://www.lydsy.com/JudgeOnline/problem.php?id=1014 Description 火星人 ...

  5. BZOJ 1014 [JSOI2008]火星人prefix (splay+二分答案+字符串hash)

    题目大意:维护一个字符串,支持插入字符和替换字符的操作,以及查询该字符串两个后缀的最长公共前缀长度 乍一看以为是后缀数组,然而并没有可持久化后缀数组(雾) 看题解才知道这是一道splay题,首先要对s ...

  6. bzoj 1014 [JSOI2008]火星人prefix——splay+哈希

    题目:https://www.lydsy.com/JudgeOnline/problem.php?id=1014 用splay维护字符串,每个点记录子树的哈希值,然后二分查询. 二分不是把两个点的哈希 ...

  7. BZOJ 1014 [JSOI2008]火星人prefix | Splay维护哈希值

    题目: 题解: #include<cstdio> #include<algorithm> #include<cstring> typedef long long l ...

  8. bzoj 1014: [JSOI2008]火星人prefix hash && splay

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

  9. 求帮看!!!!BZOJ 1014 [JSOI2008]火星人prefix

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

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

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

随机推荐

  1. java 泛型类

     Java泛型中的标记符含义:  E - Element (在集合中使用,因为集合中存放的是元素) T - Type(Java 类) K - Key(键) V - Value(值) N - Numbe ...

  2. Android 时间轴TimeLine

    代码:这里

  3. Android HandlerThread 使用

    HandlerThread 继承了 Thread,添加了 looper,queue 的支持.可以为 Handler 提供线程服务,并可对 执行的任务进行简单的管理. Handler 默认工作在主线程, ...

  4. Sublime Text3中文乱码及tabs中文方块的解决方案

    一.文本出现中文乱码问题 方案1 1.打开Sublime Text 3,按Ctrl+-打开控制行,复制粘贴以下python代码,然后回车运行. 2. 复制并粘贴如下代码: import urllib. ...

  5. 配置hibernate根据实体类自动建表功能

    Hibernate支持自动建表,在开发阶段很方便,可以保证hbm与数据库表结构的自动同步. 如何使用呢?很简单,只要在hibernate.cfg.xml里加上如下代码 Xml代码<propert ...

  6. svn: E230001: Server SSL certificate verification failed

    TortoiseSvn是好的 命令行svn 的时候 有问题 ,也加了--no-auth-cache --non-interactive参数 svn list 地址 选下p 就好. http://sta ...

  7. POJ 1577 Falling Leaves

    题意:给出一些字符串,从上到下的建树,输出其前序遍历 像前面那一题一样,先建树,然后再递归前序遍历 不过想像上一题那样用数组建树,建树和上题一样的办法,可是应该怎么输出前序遍历呢= = 还是看的题解= ...

  8. 如何解决:ERROR: the user data image is used by another emulator. aborting 的问题

    问题概述: 在启动Android模拟器时出现以下错误,导致启动失败. ERROR: the user data image is used by another emulator. aborting. ...

  9. Java 知识点:序列化

    首先明确一点:默认的序列化方法速度很慢,因为需要对整个对象和他的类都进行保存,因此我们建议自定义序列化格式. ObjectInputStream和ObjectOutputStream 用途 Objec ...

  10. MongoDB入门分享-笔记整理精选

    最近在学习MongoDB,怕以后忘记,自己做了一个整理,给不知道的小伙伴一起分享学习一下. 第一步> 首先到官网下载,安装MongoDB.(注意MongoDB还有一个可视化管理工具叫: Mong ...