题目大意:一个字符串三个操作:①求两个后缀的LCP②插入一个字符③修改一个字符。

  前几天刚学了hash+二分求lcp,就看到这题。

  原来splay还能这么用?!原来splay模板这么好写?我以前写的splay是假的吧woc

  splay每个节点代表一个字符,并维护这个子树代表一个子串的哈希值。因为splay旋转不破坏树结构,所以不论怎么旋转这棵splay树都能代表这个字符串。

  预处理处理少了调了半天呜呜呜

  赶紧跑去更新自己的splay模板

#include<iostream>
#include<cstring>
#include<cstdlib>
#include<cstdio>
#define which(x) (son[fa[x]][1]==x)
#define ull unsigned long long
using namespace std;
const int maxn=;
int n,m,x,y,tot,root;
int fa[maxn],son[maxn][],size[maxn],s[maxn];
ull hs[maxn],mul[maxn];
char st[maxn],ch[maxn],ch2[maxn];
void read(int &k)
{
int f=;k=;char c=getchar();
while(c<''||c>'')c=='-'&&(f=-),c=getchar();
while(c<=''&&c>='')k=k*+c-'',c=getchar();
k*=f;
}
void update(int x)
{
size[x]=size[son[x][]]+size[son[x][]]+;
hs[x]=hs[son[x][]]+mul[size[son[x][]]]*s[x]+mul[size[son[x][]]+]*hs[son[x][]];
}
void rotate(int x)
{
int f=fa[x];
bool k=which(x);
son[f][k]=son[x][!k];
son[x][!k]=f;
son[fa[f]][which(f)]=x;
fa[son[f][k]]=f;
fa[x]=fa[f];
fa[f]=x;
size[x]=size[f];
hs[x]=hs[f];
update(f);
}
void splay(int x,int g)
{
while(fa[x]!=g)
{
int f=fa[x];
if(fa[f]==g)
{
rotate(x);
break;
}
if(which(x)^which(f))rotate(x);
else rotate(f);
rotate(x);
}
if(!g)root=x;
}
int rank(int x,int k)
{
if(k<=size[son[x][]])return rank(son[x][],k);
else if(k==(size[son[x][]]+))return x;
else return rank(son[x][],k-size[son[x][]]-);
}
int build(int l,int r,int f)
{
if(l>r)return ;
int x=++tot,mid=(l+r)>>;
fa[x]=f;s[x]=(int)(st[mid]-'a')+;
son[x][]=build(l,mid-,x);
son[x][]=build(mid+,r,x);
update(x);
return x;
}
void insert(int k,int ch)
{
int x=rank(root,k),y=rank(root,k+);
splay(x,);splay(y,x);
s[++tot]=ch;
fa[tot]=y;son[y][]=tot;
update(tot);update(y);update(x);
}
void change(int k,int ch)
{
int x=rank(root,k);
splay(x,);
s[x]=ch;
update(x);
}
int lcp(int kx,int ky)
{
int l=,r=n;
while(l<r)
{
int mid=(l+r+)>>;
if(ky+mid>n+)
{
r=mid-;
continue;
}
int x=rank(root,kx-),y=rank(root,kx+mid);
splay(x,);splay(y,x);
ull haxi=hs[son[y][]];
x=rank(root,ky-),y=rank(root,ky+mid);
splay(x,);splay(y,x);
if(haxi==hs[son[y][]])l=mid;
else r=mid-;
}
return l;
}
int main()
{
scanf("%s",st+);
n=strlen(st+);
mul[]=;
for(int i=;i<=;i++)mul[i]=mul[i-]*;
root=build(,n+,);
read(m);
for(int i=;i<=m;i++)
{
scanf("%s",ch);
if(ch[]=='Q')
{
read(x);read(y);
if(x>y)swap(x,y);
if(x!=y)printf("%d\n",lcp(x+,y+));
else printf("%d\n",n-x+);
}
if(ch[]=='R')
{
read(x);
scanf("%s",ch2);
change(x+,(int)(ch2[]-'a')+);
}
if(ch[]=='I')
{
read(x);
scanf("%s",ch2);
insert(x+,(int)(ch2[]-'a')+);
n++;
}
}
return ;
}

bzoj1014: [JSOI2008]火星人prefix(splay+hash+二分)的更多相关文章

  1. bzoj1014: [JSOI2008]火星人prefix splay+hash+二分

    Description 火星人最近研究了一种操作:求一个字串两个后缀的公共前缀.比方说,有这样一个字符串:madamimadam,我们将这个字符串的各个字符予以标号:序号: 1 2 3 4 5 6 7 ...

  2. 【bzoj1014】[JSOI2008]火星人prefix Splay+Hash+二分

    题目描述 火星人最近研究了一种操作:求一个字串两个后缀的公共前缀.比方说,有这样一个字符串:madamimadam,我们将这个字符串的各个字符予以标号:序号: 1 2 3 4 5 6 7 8 9 10 ...

  3. BZOJ 1014 [JSOI2008]火星人prefix (Splay + Hash + 二分)

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

  4. bzoj1014: [JSOI2008]火星人prefix splay+hash

    我写的代码好像自古以来就是bzoj不友好型的 本地跑的比std快,但是交上去巧妙被卡 答案...应该是对的,拍了好久了 #include <bits/stdc++.h> #define M ...

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

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

  6. BZOJ 1014: [JSOI2008]火星人prefix( splay + hash )

    用splay维护序列, 二分+hash来判断LCQ.. #include<bits/stdc++.h> using namespace std; typedef unsigned long ...

  7. 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$ ...

  8. BZOJ1014: [JSOI2008]火星人prefix(splay 二分 hash)

    题意 题目链接 Sol 一眼splay + 二分hash,不过区间splay怎么写来着呀 试着写了两个小时发现死活不对 看了一下yyb的代码发现自己根本就不会splay.... // luogu-ju ...

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

    Description 火星人最近研究了一种操作:求一个字串两个后缀的公共前缀.比方说,有这样一个字符串:madamimadam,我们将这个字符串的各个字符予以标号:序号: 1 2 3 4 5 6 7 ...

  10. BZOJ1014[JSOI2008]火星人prefix(splay维护hash)

    Description 火星人最近研究了一种操作:求一个字串两个后缀的公共前缀.比方说,有这样一个字符串:madamimadam,我们将这个字符串的各个字符予以标号:序号: 1 2 3 4 5 6 7 ...

随机推荐

  1. lintcode142 O(1)时间检测2的幂次

    O(1)时间检测2的幂次 用 O(1) 时间检测整数 n 是否是 2 的幂次. 您在真实的面试中是否遇到过这个题? Yes 样例 n=4,返回 true; n=5,返回 false. 二进制的n中只有 ...

  2. 【第五章】MySQL数据库的安全机制

    MySQL权限表MySQL用户管理MySQL权限管理SSL加密连接

  3. maven项目中没有resource文件夹的问题

    之前使用eclipse创建maven项目,文件夹都是建好的,这几次创建,都没有resource文件夹,需要手动创建resource. 现象描述 在eclipse中,创建maven项目有两种方式: 一种 ...

  4. vscode开发智能合约

    开发工具 EOS 开发终极神器-vscode (你绝对找不到的干货) lome · 2018年04月19日 · 最后由 18636292520 回复于 2018年09月15日 · 15672 次阅读 ...

  5. RedHat/CentOS利用iso镜像做本地yum源

    在这里用iso或者光盘做本地yum源的方法是差不多的,只是用光盘的话Linux系统会自动挂载,用iso镜像的或需要手动挂载,这里就说挂载iso的方法吧. (1) 创建iso存放目录和挂载目录 mkdi ...

  6. NFC学习总结二

    移动支付这事情热了总归还是会回归理性,就如同之前的10几年间的几次轮回一样.字面上看,移动支付比支付大也不大可能,有相同,有扩展,有交集有不通才是. NFC这事情也是说了快十年了,真心希望它能回归到其 ...

  7. 2017-2018-2 20172323 『Java程序设计』课程 结对编程练习_四则运算 2

    相关过程截图 关键代码解释 将运算式分开的代码 String[] result = num.split("\\s"); 将输入的num以空格为间隔符号分开,将每一个间隔开的字符存入 ...

  8. 基于TensorFlow解决手写数字识别的Softmax方法、多层卷积网络方法和前馈神经网络方法

    一.基于TensorFlow的softmax回归模型解决手写字母识别问题 详细步骤如下: 1.加载MNIST数据: input_data.read_data_sets('MNIST_data',one ...

  9. LintCode-380.两个链表的交叉

    两个链表的交叉 请写一个程序,找到两个单链表最开始的交叉节点. 注意事项 如果两个链表没有交叉,返回null. 在返回结果后,两个链表仍须保持原有的结构. 可假定整个链表结构中没有循环. 样例 下列两 ...

  10. C# Dsoframer.ocx 如何在winform中嵌入Excel,内嵌Excel,word

    如果你还不太清楚Dspframer.ocx怎么放到窗体上就看上一篇文章,里面详细介绍了是如何放到窗体上的. 链接:http://www.cnblogs.com/pingming/p/4182045.h ...