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 ...
随机推荐
- vue-loader 调用了cssLoaders方法配置了css加载器属性。
module: { loaders: [ // 这里也是相应的配置,test就是匹配文件,loader是加载器, { test: /\.vue$/, loader: 'vue' }, { test: ...
- Unity 添加鼠标右键事件
把此类放到 Editor下使用就OK using UnityEngine; using System.Collections; using System.Collections.Generic; us ...
- js-打地鼠游戏开发
[生成画布] 第1课[随机生成地鼠] 第2课[定时生成地鼠] 第3课[打地鼠完结篇] 第4课 优酷在线播放地址 http://list.youku.com/albumlist/show?id=2939 ...
- jquery对象和javascript对象即DOM对象相互转换
jquery对象和javascript对象即DOM对象相互转换 1. DOM 对象转成 jQuery 对象对于已经是一个 DOM 对象,只需要用 $() 把DOM对象包装起来,就可以获得一个 jQue ...
- malloc原理和内存碎片【转】
转自:http://www.cnblogs.com/zhaoyl/p/3820852.html 当一个进程发生缺页中断的时候,进程会陷入内核态,执行以下操作: 1.检查要访问的虚拟地址是否合法 2.查 ...
- 64_p8
python2-cotyledon-tests-1.6.7-2.fc26.noarch.rpm 12-Feb-2017 10:28 23182 python2-couchdb-1.0-6.fc26.n ...
- videojs做直播、弹幕
从上一年开始,我们开始接触直播,现在直播成本真的很低,很多CDN供应商都有提供,本文只是大概讲述播放器这个话题. 开始调研 播放格式,我挑了三种.分别是HLS,RTMP,HTTP-FLV. 下面简单说 ...
- 教你如何修改FireFox打开新标签页(NewTab Page)的行列数
FireFox的打开新建标签页(即NewTab Page)默认只能显示3x3个网站缩略图,这9个自定义的网站,非常方便快捷,什么hao123的弱爆了,本人从未用过此类导航网站,曾经用过的也只是abou ...
- 对 makefile 中 .DEFAULT 的理解
上例子: all:gao @echo "final".DEFAULT: @echo "In default" 由于 gao 是一个前提条件,但是 makefil ...
- free之后将指针置为NULL
free一个指针,只是将指针指向的内存空间释放掉了,并没有将指针置为NULL,指针仍指向被释放掉的内存的地址,在判断指针是否为NULL的时候,通常是通过if(pt == NULL) ,这时,导致指针成 ...