bzoj 1014 LCP 二分 Hash 匹配
求同一字符串的两个后缀的最长公共前缀。
将字符串按位置放到Splay中维护(每个节点还维护一下该子树的hash),然后二分前缀的长度,用splay计算出指定范围的hash,按hash是否相等来判断是否相同。
/**************************************************************
Problem: 1014
User: idy002
Language: C++
Result: Accepted
Time:7188 ms
Memory:4900 kb
****************************************************************/ #include <cstdio>
#include <iostream>
#include <cstring>
#define maxn 100030
using namespace std; typedef unsigned long long ulng; struct Splay {
int pre[maxn], son[maxn][], ch[maxn], siz[maxn], ntot, root;
ulng hash[maxn];
ulng power[maxn]; int newnode( int p, int c ) {
int nd = ++ntot;
pre[nd] = p;
son[nd][] = son[nd][] = ;
ch[nd] = c;
siz[nd] = ;
hash[nd] = c;
return nd;
}
void update( int nd ) {
int ls = son[nd][], rs = son[nd][];
siz[nd] = siz[ls]+siz[rs]+;
hash[nd] = hash[ls]*power[siz[rs]+]+ch[nd]*power[siz[rs]]+hash[rs];
}
int build( int p, const char *str, int lf, int rg ) { // [lf,rg]
if( lf>rg ) return ;
if( lf==rg ) return newnode(p,str[lf]-'a');
int mid = (lf+rg)>>;
int nd = newnode( p, str[mid]-'a' );
son[nd][] = build( nd, str, lf, mid- );
son[nd][] = build( nd, str, mid+, rg );
update( nd );
return nd;
}
void init( const char *str ) {
root = ntot = ;
power[] = 1ULL;
for( int i=; i<maxn; i++ )
power[i] = power[i-]*27ULL; root = newnode( , 'a'-'a' );
int rnd = son[root][] = newnode( root, 'a'-'a' );
son[rnd][] = build( rnd, str, , strlen(str)- );
update( rnd );
update( root );
}
void rotate( int nd, int d ) {
int p = pre[nd];
int s = son[nd][!d];
int ss = son[s][d]; son[nd][!d] = ss;
son[s][d] = nd;
if( p ) son[p][ nd==son[p][] ] = s;
else root = s; pre[s] = p;
pre[nd] = s;
if( ss ) pre[ss] = nd; update( nd );
update( s );
}
void splay( int nd, int top= ) {
while( pre[nd]!=top ) {
int p = pre[nd];
int nl = nd==son[p][];
if( pre[p]==top ) {
rotate( p, nl );
} else {
int pp = pre[p];
int pl = p==son[pp][];
if( nl==pl ) {
rotate( pp, pl );
rotate( p, nl );
} else {
rotate( p, nl );
rotate( pp, pl );
}
}
}
}
int find( int pos ) {
int nd = root;
while() {
int ls = siz[son[nd][]];
if( nd== ) while(); if( pos<=ls ) {
nd = son[nd][];
} else if( pos>=ls+ ) {
nd = son[nd][];
pos -= ls+;
} else return nd;
}
}
void add_ch( int pos, int c ) {
int lnd = find(pos);
int rnd = find(pos+);
splay(lnd);
splay(rnd,lnd);
son[rnd][] = newnode( rnd, c );
splay( son[rnd][] );
}
void chg_ch( int pos, int c ) {
int nd = find(pos);
ch[nd] = c;
update( nd );
splay( nd );
}
ulng qu_hash( int lf, int rg ) {
int lnd = find(lf-);
int rnd = find(rg+);
splay( lnd );
splay( rnd, lnd );
return hash[son[rnd][]];
}
inline int size() { return siz[root]-; }
}; Splay T;
char str[maxn];
int m; int main() {
scanf( "%s", str );
T.init(str);
scanf( "%d", &m );
while(m--) {
char ch[];
int pos, sa, sb;
scanf( "%s", ch );
if( ch[]=='I' ) {
scanf( "%d%s", &pos, ch );
pos++;
T.add_ch( pos, ch[]-'a' );
} else if( ch[]=='R' ) {
scanf( "%d%s", &pos, ch );
pos++;
T.chg_ch( pos, ch[]-'a' );
} else {
scanf( "%d%d", &sa, &sb );
sa++, sb++;
if( T.qu_hash(sa,sa) != T.qu_hash(sb,sb) ) {
printf( "0\n" );
continue;
}
int len = T.size() - max(sa-,sb-) + ;
int rl = , rr = len;
while( rl<rr ) {
int md = (rl+rr+)>>;
ulng ha = T.qu_hash( sa, sa+md- );
ulng hb = T.qu_hash( sb, sb+md- );
if( ha==hb ) rl = md;
else rr = md-;
}
printf( "%d\n", rl );
}
}
}
bzoj 1014 LCP 二分 Hash 匹配的更多相关文章
- bzoj 1014 splay维护hash值
被后缀三人组虐了一下午,写道水题愉悦身心. 题很裸,求lcq时二分下答案就行了,写的不优美会被卡时. (写题时精神恍惚,不知不觉写了快两百行...竟然调都没调就A了...我还是继续看后缀自动机吧... ...
- BZOJ 1014 [JSOI2008]火星人prefix (Splay + Hash + 二分)
1014: [JSOI2008]火星人prefix Time Limit: 10 Sec Memory Limit: 162 MBSubmit: 8112 Solved: 2569[Submit] ...
- BZOJ 1014: [JSOI2008]火星人prefix [splay 二分+hash] 【未完】
1014: [JSOI2008]火星人prefix Time Limit: 10 Sec Memory Limit: 162 MBSubmit: 6243 Solved: 2007[Submit] ...
- [BZOJ 1014] [JSOI2008] 火星人prefix 【Splay + Hash】
题目链接:BZOJ - 1014 题目分析 求两个串的 LCP ,一种常见的方法就是 二分+Hash,对于一个二分的长度 l,如果两个串的长度为 l 的前缀的Hash相等,就认为他们相等. 这里有修改 ...
- BZOJ 1014: [JSOI2008]火星人prefix( splay + hash )
用splay维护序列, 二分+hash来判断LCQ.. #include<bits/stdc++.h> using namespace std; typedef unsigned long ...
- BZOJ1014: [JSOI2008]火星人prefix(splay 二分 hash)
题意 题目链接 Sol 一眼splay + 二分hash,不过区间splay怎么写来着呀 试着写了两个小时发现死活不对 看了一下yyb的代码发现自己根本就不会splay.... // luogu-ju ...
- BZOJ 3790 神奇项链 hash/后缀自动机+贪心
Description 母亲节就要到了,小 H 准备送给她一个特殊的项链.这个项链可以看作一个用小写字母组成的字符串,每个小写字母表示一种颜色. 为了制作这个项链,小 H 购买了两个机器.第一个机器可 ...
- Bzoj 1014&Luogu 4036 火星人Prefix(FHQ-Treap)
题面 洛谷 Bzoj 题解 首先,这种带修改的是不能用$SA$的,然后,我们做$SA$的题一般也能二分+$Hash$,所以不妨考虑用$FHQ-Treap$维护树,然后查询就用二分+$Hash$. $H ...
- UVALive 2238 Fixed Partition Memory Management(二分完美匹配)
题意:计算机中有一些固定大小的内存,内存越大,处理速度越快.对于一个程序,加入不同的内存空间,处理所需时间不同.现给出m个内存空间,n个程序,对于每个程序程序,有k组数据(s,t),分别表示当程序 i ...
随机推荐
- ActiveMQ笔记之安装(Linux)
1. 基本概念 MQ(MessageQueue),消息队列,是一个消息接收和转发的容器. Apache ActiveMQ是一个JMS Provider实现. 2. 安装 从官网下载安装包: wget ...
- webpack中的静态资源处理
你可能已经注意到,在我们的项目结构里,有两个静态文件的路径,分别是:src/assets 和 static/.那这两个到底有什么区别呢? Webpacked 资源 为了回答这个问题,我们首先需要理解w ...
- ASLR
@author:dlive ASLR address space layout randomization 微软从windows vista/windows server 2008(kernel ve ...
- 非交互式shell脚本案例-实现自主从oracle数据库获取相关数据,并在制定目录生成相应规则的文件脚本
get_task_id 脚本内容 #!/usr/bin/expect#配置登陆数据库的端口set port 22#配置登陆数据库的ip地址set oracleip 10.0.4.41#配置数据库实例名 ...
- Java中Enum的使用
http://www.cnblogs.com/happyPawpaw/archive/2013/04/09/3009553.html Enum有一个好处,可以使用EnumMap和EnumSet,而En ...
- Dagger:快速的依赖注入for 安卓&Java
Dagger:快速的依赖注入for 安卓&Java 2014年5月8日 星期四 15:29 官网: http://square.github.io/dagger/ GitHub: https: ...
- HDU 4614 Vases and Flowers(线段树+记录区间始末点或乱搞)
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=4614 题目大意:有n个空花瓶,有两种操作: 操作①:给出两个数字A,B,表示从第A个花瓶开始插花,插B ...
- DNS使用TCP还是UDP?
DNS同时占用UDP和TCP端口53是公认的,这种单个应用协议同时使用两种传输协议的情况在TCP/IP栈也算是个另类.下面将介绍DNS分别在什么情况下使用这两种协议. TCP与UDP简介 TCP ...
- JavaScript 中typeof、instanceof 与 constructor 的区别?
typeof.instanceof 与 constructor 详解 typeof 一元运算符 返回一个表达式的数据类型的字符串,返回结果为js基本的数据类型,包括number,boolean,st ...
- 双缓冲解决控制台应用程序输出“闪屏”(C/C++,Windows)
使用 C 语言编写游戏的小伙伴们想必起初都要遇到这样的问题,在不断清屏输出数据的过程中,控制台中的输出内容会不断地闪屏.出现这个问题的原因是程序对数据处理花掉的时间影响到了数据显示,或许你可以使用局部 ...