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 ...
随机推荐
- 去掉input获取focus时的边框
贴图,问题如下: 尽管已经设置输入框的border为none,当输入框focus时扔会出现浏览器自带的边框 解决方法,添加如下样式即可,.fs_input为输入框样式 ---------------- ...
- Linux内核中的常用宏container_of其实很简单【转】
转自:http://blog.csdn.net/npy_lp/article/details/7010752 开发平台:Ubuntu11.04 编 译器:gcc version 4.5.2 (Ubun ...
- 【swupdate文档 四】SWUpdate:使用默认解析器的语法和标记
SWUpdate:使用默认解析器的语法和标记 介绍 SWUpdate使用库"libconfig"作为镜像描述的默认解析器. 但是,可以扩展SWUpdate并添加一个自己的解析器, ...
- PHP 快速建立一个对象
前言 PHP 中的数组(尤其关联数组)是经常使用的 —— 因为方便.在一些框架中也经常见到返回数组格式的配置参数.然而有些时候可能需要对象而非数组类型的配置参数,在查阅网络资料后找到了方法,作以记录. ...
- 「caffe编译bug」 undefined reference to `boost::match_results<__gnu_cxx::__normal_iterator<char const*, std::__cxx11
CXX/LD -o .build_release/tools/test_net.binCXX/LD -o .build_release/tools/convert_annoset.binCXX/LD ...
- Netty框架入门
一.概述 Netty是由JBOSS提供的一个java开源框架. Netty提供异步的.事件驱动的网络应用程序框架和工具,用以快速开发高性能.高可靠性的网络服务器和客户端程序. 二. ...
- MYSQL三种安装方式--二进制包安装
1. 把二进制包下载到/usr/local/src下 2. 如果是tar.gz包,则使用tar zxvf 进行解压 如果是tar包,则可以使用tar xvf 进行解压 3. $ mv mysql-5. ...
- [ python ] 网络编程(2)
黏包问题 这样一个实例 import socket import subprocess sk_server = socket.socket() # 创建 socket对象 sk_server.bind ...
- highcharts自定义导出文件格式(csv) highcharts的一些使用心得
highcharts是国外的一个图表插件,包括各种数据图形展示,柱形图,线性图等等,是手机端和pc端最好的图表插件之一,相比于百度的echarts更加轻便和易懂.链接http://www.hchart ...
- web.xml中的dispatchservlet后,js,css,甚至gif都不能正常显示
这个可以说是很多初学Springmvc的人都会碰到一个令人头痛的问题 那就是为什么我配置好web.xml中的dispatchservlet后,js,css,甚至gif都不能正常显示了 我们来看看我们配 ...