题目链接

后缀数组显然不行啊。求LCP还可以哈希+二分,于是考虑用平衡树维护哈希值。

\[某一节点的哈希值 = hs[lson]*base^{sz[rson]+1} + s[rt]*base^{sz[rson]} + hs[rson]
\]

好像跑的很慢。。

//4800kb	5492ms
#include <cstdio>
#include <cctype>
#include <cstring>
#include <algorithm>
#define lson son[x][0]
#define rson son[x][1]
#define gc() getchar()
typedef unsigned long long ull;
const int N=110000;
const ull base=31; int root,size,len,sz[N],fa[N],son[N][2],s[N];
char tmp[N];
ull hs[N],pw[N]; inline int read()
{
int now=0;register char c=gc();
for(;!isdigit(c);c=gc());
for(;isdigit(c);now=now*10+c-'0',c=gc());
return now;
}
inline char Get_opt()
{
char c=gc();
while(c!='Q'&&c!='R'&&c!='I') c=gc();
return c;
}
inline char Get_char()
{
char c=gc();
while(!isalpha(c)) c=gc();
return c;
}
inline void Update(int x)
{
int rs=rson;
sz[x]=sz[lson]+sz[rs]+1,
hs[x]=hs[lson]*pw[sz[rs]+1]+s[x]*pw[sz[rs]]+hs[rs];
}
void Build(int l,int r,int f)
{
if(l>r) return;
int m=l+r>>1;
son[f][m>f]=m, fa[m]=f, s[m]=tmp[m]-'a'+1;
if(l==r) sz[l]=1, hs[l]=s[m];
else Build(l,m-1,m), Build(m+1,r,m), Update(m);
}
void Rotate(int x,int &k)
{
int a=fa[x],b=fa[a],l=son[a][1]==x,r=l^1;
if(a==k) k=x;
else son[b][son[b][1]==a]=x;
fa[a]=x, fa[x]=b, fa[son[x][r]]=a, son[a][l]=son[x][r], son[x][r]=a;
Update(a);
}
void Splay(int x,int &k)
{
while(x!=k)
{
int a=fa[x];
if(a!=k) son[a][1]==x^son[fa[a]][1]==a?Rotate(x,k):Rotate(a,k);
Rotate(x,k);
}
Update(x);
}
int Kth(int k,int x)
{
while(1)
{
if(sz[lson]+1==k) return x;
if(sz[lson]<k) k-=sz[lson]+1, x=rson;
else x=lson;
}
}
inline int Split(int l,int r)//Get(l,r)
{
int x=Kth(l,root),y=Kth(r,root);
Splay(x,root), Splay(y,son[x][1]);
return son[y][0];
}
inline bool Check(int x,int y,int len)
{
ull v1=hs[Split(x,x+len+1)], v2=hs[Split(y,y+len+1)];
return v1==v2;
}
void Query(int x,int y)
{
int l=1,r=std::min(size-x-1,size-y-1),mid;
while(l<=r){
if(Check(x,y,mid=l+r>>1)) l=mid+1;
else r=mid-1;
}
printf("%d\n",r);
}
void Modify(int p,char c)
{
int x=Kth(p,root);
Splay(x,root), s[x]=c-'a'+1, Update(x);
}
void Insert(int p,char c)
{
// Split(p,p+1);//不能只用Split()!这的p是下标,不一定是编号!
int p1=Kth(p,root),p2=Kth(p+1,root);
Splay(p1,root), Splay(p2,son[root][1]);
int x=++size;
sz[x]=1, hs[x]=s[x]=c-'a'+1, fa[x]=p2, son[p2][0]=x;
Update(p2), Update(p1);
} int main()
{
pw[0]=1;
for(int i=1; i<N; ++i) pw[i]=pw[i-1]*31;
scanf("%s",tmp+2), len=strlen(tmp+2);
size=len+2, root=len+3>>1, Build(1,size,0);
int m=read(),x,y; char opt;
while(m--)
switch(opt=Get_opt(),opt)
{
case 'Q':x=read(),y=read(),Query(x,y); break;
case 'R':x=read(),Modify(x+1,Get_char()); break;
case 'I':x=read(),Insert(x+1,Get_char()); break;
}
return 0;
}

BZOJ.1014.[JSOI2008]火星人(Splay 二分 Hash)的更多相关文章

  1. BZOJ 1014: [JSOI2008]火星人prefix [splay 二分+hash] 【未完】

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

  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 )

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

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

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

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

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

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

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

  7. [BZOJ 1014] [JSOI2008] 火星人prefix 【Splay + Hash】

    题目链接:BZOJ - 1014 题目分析 求两个串的 LCP ,一种常见的方法就是 二分+Hash,对于一个二分的长度 l,如果两个串的长度为 l 的前缀的Hash相等,就认为他们相等. 这里有修改 ...

  8. BZOJ 1014: [JSOI2008]火星人prefix

    Sol Splay+Hash+二分答案. 用Splay维护Hash,二分答案判断. 复杂度 \(O(nlog^2n)\) PS:这题调了两个晚上因为没开long long.许久不写数据结构题感觉写完整 ...

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

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

随机推荐

  1. CM记录-CDH大数据平台实施经验总结2016(转载)

    CDH大数据平台实施经验总结2016(转载) 2016年负责实施了一个生产环境的大数据平台,用的CDH平台+docker容器的方式,过了快半年了,现在把总结发出来. 1. 平台规划注意事项 1.1 业 ...

  2. Jenkins 01——简介

    Jenkins是一个开源软件项目,一个可扩展的持续集成引擎.旨在提供一个开放易用的软件平台,使软件的持续集成变成可能. 持续集成是一种开发实践,需要开发人员定期将代码集成到共享存储库中.这个概念意在消 ...

  3. bzoj千题计划193:bzoj2460: [BeiJing2011]元素

    http://www.lydsy.com/JudgeOnline/problem.php?id=2460 按魔力值从小到大排序构造线性基 #include<cstdio> #include ...

  4. Mac下安装zsh(Oh My ZSH)的shell,替代原有的bash

    说明:一开始装zsh我是拒绝的,因为这个东西装简单,卸载很难,并且装了之后默认Shell的配置文件不能用了,比如~/.bashrc这些.所以在装的时候要再三考虑好! 官网:http://ohmyz.s ...

  5. 【ARTS】01_07_左耳听风-20181224~1230

    ARTS: Algrothm: leetcode算法题目 Review: 阅读并且点评一篇英文技术文章 Tip/Techni: 学习一个技术技巧 Share: 分享一篇有观点和思考的技术文章 Algo ...

  6. 直接读取修改exe文件

    1. 前言 配置器的编写有很多的方式,主要是直接修改原始的受控端的程序,有的方式是把受控端和配置信息都放到控制端程序的内部,在需要配置受控端的时候直接输入配置信息,生成受控端:也有的方式是在外部直接修 ...

  7. Linux下利用backtrace追踪函数调用堆栈以及定位段错误【转】

    转自:https://www.linuxidc.com/Linux/2012-11/73470p2.htm 通常情况系,程序发生段错误时系统会发送SIGSEGV信号给程序,缺省处理是退出函数.我们可以 ...

  8. win10 安装IIS说明操作

    1.点左下角的Windows,所有应用,找到Windows系统,打开控制面板. 2.进入控制面板之后点击程序,可能你的控制面板和图片里的不太一样,不过没关系,找到程序两个字点进去就行. 3.接下来,在 ...

  9. javascript-词法分析解析

    <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8&quo ...

  10. android view的多种移动方式(测试集合)

    前言 由于最近在写一个涉及移动方面的自定义View,在做移动的时候用到了类似offsetTopAndBottom .setTranslationY.scrollTo.scrollBy等方法,对于他们的 ...