求同一字符串的两个后缀的最长公共前缀。

将字符串按位置放到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 匹配的更多相关文章

  1. bzoj 1014 splay维护hash值

    被后缀三人组虐了一下午,写道水题愉悦身心. 题很裸,求lcq时二分下答案就行了,写的不优美会被卡时. (写题时精神恍惚,不知不觉写了快两百行...竟然调都没调就A了...我还是继续看后缀自动机吧... ...

  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] 【未完】

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

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

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

  5. BZOJ 1014: [JSOI2008]火星人prefix( splay + hash )

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

  6. BZOJ1014: [JSOI2008]火星人prefix(splay 二分 hash)

    题意 题目链接 Sol 一眼splay + 二分hash,不过区间splay怎么写来着呀 试着写了两个小时发现死活不对 看了一下yyb的代码发现自己根本就不会splay.... // luogu-ju ...

  7. BZOJ 3790 神奇项链 hash/后缀自动机+贪心

    Description 母亲节就要到了,小 H 准备送给她一个特殊的项链.这个项链可以看作一个用小写字母组成的字符串,每个小写字母表示一种颜色. 为了制作这个项链,小 H 购买了两个机器.第一个机器可 ...

  8. Bzoj 1014&Luogu 4036 火星人Prefix(FHQ-Treap)

    题面 洛谷 Bzoj 题解 首先,这种带修改的是不能用$SA$的,然后,我们做$SA$的题一般也能二分+$Hash$,所以不妨考虑用$FHQ-Treap$维护树,然后查询就用二分+$Hash$. $H ...

  9. UVALive 2238 Fixed Partition Memory Management(二分完美匹配)

    题意:计算机中有一些固定大小的内存,内存越大,处理速度越快.对于一个程序,加入不同的内存空间,处理所需时间不同.现给出m个内存空间,n个程序,对于每个程序程序,有k组数据(s,t),分别表示当程序 i ...

随机推荐

  1. 天梯赛 L2-014 列车调度 (模拟)

    火车站的列车调度铁轨的结构如下图所示. Figure 两端分别是一条入口(Entrance)轨道和一条出口(Exit)轨道,它们之间有N条平行的轨道.每趟列车从入口可以选择任意一条轨道进入,最后从出口 ...

  2. 线程句柄和线程ID的区别

    ●CreateThread() API 用于创建线程. API 返回同时线程句柄,并通过参数得到线程标识符 (ID). 线程句柄有完全访问权创建线程对象. 运行线程时线程 ID 唯一标识线程在系统级别 ...

  3. 【Explain】mysql之explain详解(分析索引的最佳使用)

    在日常工作中,我们会有时会开慢查询去记录一些执行时间比较久的SQL语句,找出这些SQL语句并不意味着完事了,些时我们常常用到explain 这个命令来查看一个这些SQL语句的执行计划,查看该SQL语句 ...

  4. perl6 struct2-045 EXP

    测试站点: http://www.yutian.com.cn/index.action http://www.hjxzyzz.com:8088/pfw/login.action 代码如下: use v ...

  5. vue头像上传

    项目四知识点 默认头像 选择头像 <template> <div class="adatar"> <img :src="adatar?ada ...

  6. UNDO自我理解总结

    [场景] 当在更新数据的时候,发现更新的值写错了,这时就需要将已经更新的地方恢复到原始数据. [基本概念] 在更新的过程中,Oracle会将原始的数据都放入到UNDO里,这样当以上情况发生后,就可以从 ...

  7. centos上git搭建

    1 git的安装需要一些包: yum install curl-devel expat-devel gettext-devel openssl-devel zlib-devel gcc perl-Ex ...

  8. 使用常见的网络命令查看当前网络状态——Mac OS X篇

    转载自:http://blog.csdn.net/zkh90644/article/details/50539948 操作系统拥有一套通用的实用程序来查明本地主机的有线或者无线链路状态和IP的连接情况 ...

  9. JavaScript 去字符串空格

    JavaScript 去字符串空格 (利用正则) # str为要去除空格的字符串: # 去除所有空格: str = str.replace(/\s+/g,""); # 去除两头空格 ...

  10. (总结)MySQL自带的性能压力测试工具mysqlslap详解

    PS:今天一同事问我有木有比较靠谱的mysql压力测试工具可用.其实mysql自带就有一个叫mysqlslap的压力测试工具,还是模拟的不错的.下面举例说说.mysqlslap是从5.1.4版开始的一 ...