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 ...
随机推荐
- 爬虫--PySpider框架
PySpider框架 PySpider框架的作用
- zedboard学习记录.2.PS+PL 流水灯与uart
1.建立一个工程. 硬件设计 2.IP integrator -> create block desgin;Run Block Automation. 3.add IP -> AXI GP ...
- Python作业工资管理系统(第三周)
作业内容: 实现效果: 从info.txt文件中读取员工及其工资信息,最后将修改或增加的员工工资信息也写入原info.txt文件. 效果演示: 1. 查询员工工资 2. 修改员工工资 3. 增加新员工 ...
- Mysql储存过程7: case
#用在储存过程中: create procedure k() begin declare number int; )); case number then select '>0'; else s ...
- Linux内核中的Cache段
Linux内核中的Cache段 原文地址:http://blogold.chinaunix.net/u2/85263/showart_1743693.html 最近移植LEON3的内核时,了解了一些简 ...
- hdu 2475 BOX (splay)
版权声明:本文为博主原创文章,未经博主允许不得转载. hdu 2475 Splay树是一种神奇的东西... 题意: 有一些箱子,要么放在地上,要么放在某个箱子里面 . 现在有两种操作: (1) MOV ...
- Linux/Unix 怎样找出并删除某一时间点的文件
Linux/Unix 怎样找出并删除某一时间点的文件 在Linux/Unix系统中,我们的应用每天会产生日志文件,每天也会备份应用程序和数据库,日志文件和备份文件长时间积累会占用大量的存储空间,而有些 ...
- Webcollector应用(一)
webcollector是一个开源的Java网络爬虫框架.最近的爬虫改用java写了,对这一周的工作进行简要总结.对于内部机制了解不深入,主要侧重在应用. 一.环境搭建 需要安装一个webcollec ...
- sad 关于一些html5新属性还需要用https才能支持
像我昨天在搞一个录音的小东西 在本地正常录音正常播放 但是放到线上环境http环境上就出现了如上的错误 功能都不能正常使用 然后就改成https线上环境 然后就正常了 如上 大家有什么赐教的欢迎留言 ...
- Python+Selenium 自动化实现实例-实现文件下载
#coding=utf-8 from selenium import webdriver #实例化一个火狐配置文件 fp = webdriver.FirefoxProfile() #设置各项参数,参数 ...