BZOJ1014 火星人prefix Splay维护序列hash值+二分答案判LCP
来源:互联网 发布:cs go 准星数据 编辑:程序博客网 时间:2024/06/01 09:02
大家都很强, 可与之共勉。
Description
火星人最近研究了一种操作:求一个字串两个后缀的公共前缀。比方说,有这样一个字符串:madamimadam,我们将这个字符串的各个字符予以标号:序号: 1 2 3 4 5 6 7 8 9 10 11 字符 m a d a m i m a d a m 现在,火星人定义了一个函数LCQ(x, y),表示:该字符串中第x个字符开始的字串,与该字符串中第y个字符开始的字串,两个字串的公共前缀的长度。比方说,LCQ(1, 7) = 5, LCQ(2, 10) = 1, LCQ(4, 7) = 0 在研究LCQ函数的过程中,火星人发现了这样的一个关联:如果把该字符串的所有后缀排好序,就可以很快地求出LCQ函数的值;同样,如果求出了LCQ函数的值,也可以很快地将该字符串的后缀排好序。 尽管火星人聪明地找到了求取LCQ函数的快速算法,但不甘心认输的地球人又给火星人出了个难题:在求取LCQ函数的同时,还可以改变字符串本身。具体地说,可以更改字符串中某一个字符的值,也可以在字符串中的某一个位置插入一个字符。地球人想考验一下,在如此复杂的问题中,火星人是否还能够做到很快地求取LCQ函数的值。
Input
第一行给出初始的字符串。第二行是一个非负整数M,表示操作的个数。接下来的M行,每行描述一个操作。操作有3种,如下所示: 1、 询问。语法:Q x y,x, y均为正整数。功能:计算LCQ(x, y) 限制:1 <= x, y <= 当前字符串长度。 2、 修改。语法:R x d,x是正整数,d是字符。功能:将字符串中第x个数修改为字符d。限制:x不超过当前字符串长度。 3、 插入:语法:I x d,x是非负整数,d是字符。功能:在字符串第x个字符之后插入字符d,如果x = 0,则在字符串开头插入。限制:x不超过当前字符串长度。
Output
对于输入文件中每一个询问操作,你都应该输出对应的答案。一个答案一行。
Sample Input
madamimadam
7
Q 1 7
Q 4 8
Q 10 11
R 3 a
Q 1 7
I 10 a
Q 2 11
Sample Output
5
1
0
2
1
题解
很裸的Splay维护序列的方式,直接维护序列hash值。注意update里面不要写错了。
/************************************************************** Problem: 1014 User: Lazer2001 Language: C++ Result: Accepted Time:5920 ms Memory:7720 kb****************************************************************/# include <bits/stdc++.h>inline int read ( ) { register int x, c ; while ( isspace ( c = getchar ( ) ) ) ; for ( x = -48 + c ; isdigit ( c = getchar ( ) ) ; ( x *= 10 ) += c - 48 ) ; return x ;}# define N 101000static unsigned long long hpow [N] ;class Splay { private : struct node { int siz ; char c ; unsigned long long hval ; node *fa, *ch [2] ; inline void update ( ) { siz = ch [0] -> siz + ch [1] -> siz + 1 ; hval = ( 1ull * hpow [( ch [1] -> siz + 1 )] * ch [0] -> hval + 1ull * ( c - 'a' ) * hpow [ch [1] -> siz] + ch [1] -> hval ) ; // c - 'a'!!! } } pool [N << 1], *root, *null ; char* ss ; inline node* newnode ( node*& fa, unsigned long long hval, char c ) { static node* tp ( pool + 1 ) ; tp -> siz = 1 ; tp -> hval = hval ; tp -> c = c ; return tp -> fa = fa, tp -> ch [0] = tp -> ch [1] = null, tp ++ ; } # define isrs( p ) ( p == p -> fa -> ch [1] ) inline void rotate ( node*& p ) { bool d ( isrs ( p ) ) ; node* par = p -> fa ; par -> ch [d] = p -> ch [! d] ; if ( p -> ch [! d] != null ) p -> ch [! d] -> fa = par ; if ( par -> fa != null ) par -> fa -> ch [isrs ( par )] = p ; p -> fa = par -> fa ; par -> fa = p ; p -> ch [! d] = par ; par -> update ( ) ; p -> update ( ) ; } inline void splay ( node* p, node* tar ) { while ( p -> fa != tar ) { if ( isrs ( p ) == isrs ( p -> fa ) && p -> fa -> fa != tar ) rotate ( p -> fa ) ; rotate ( p ) ; } if ( tar == null ) root = p ; } # undef isrs inline node* build ( node*& fa, int lf, int rg ) { if ( lf > rg ) return null ; int mid = ( lf + rg ) >> 1 ; node* p = newnode ( fa, ss [mid] - 'a', ss [mid] ) ; p -> ch [0] = build ( p, lf, mid - 1 ) ; p -> ch [1] = build ( p, mid + 1, rg ) ; p -> update ( ) ; return p ; } inline node* kth ( node*& p, int k ) { int cnt = p -> ch [0] -> siz ; if ( k == cnt + 1 ) return p ; return cnt < k ? kth ( p -> ch [1], k - p -> ch [0] -> siz - 1 ) : kth ( p -> ch [0], k ) ; } inline void display ( node* p ) { if ( p == null ) return ; display ( p -> ch [0] ) ; printf ( "%c %d ch [0] = %c, ch [1] = %c hval : %llu\n", p -> c, p -> siz, p -> ch [0] -> c, p -> ch [1] -> c, p -> hval ) ; assert ( p -> siz == p -> ch [0] -> siz + p -> ch [1] -> siz + 1 ) ; display ( p -> ch [1] ) ; } public : Splay ( ) { null = pool ; null -> siz = 0 ; null -> hval = 0 ; null -> fa = null -> ch [0] = null -> ch [1] = null ; hpow [0] = 1 ; for ( int i = 1 ; i < N ; ++ i ) hpow [i] = hpow [i - 1] * 100137 ; } void build ( char* s, int lf, int rg ) { this -> ss = s ; root = build ( null, lf, rg ) ; } inline void insert ( int pos, char x ) { splay ( kth ( root, pos + 1 ), null ) ; splay ( kth ( root, pos + 2 ), root ) ; root -> ch [1] -> ch [0] = newnode ( root -> ch [1], x - 'a', x ) ; root -> ch [1] -> update ( ) ; root -> update ( ) ; } inline void modify ( int pos, char x ) { splay ( kth ( root, pos ), null ) ; splay ( kth ( root, pos + 2 ), root ) ; root -> ch [1] -> ch [0] -> hval = x - 'a' ; root -> ch [1] -> ch [0] -> c = x ; root -> ch [1] -> update ( ) ; root -> update ( ) ; } inline unsigned long long hashval ( int lf, int rg ) { splay ( kth ( root, lf ), null ) ; splay ( kth ( root, rg + 2 ), root ) ; return root -> ch [1] -> ch [0] -> hval ; } inline void display ( ) { display ( root ) ; }} S ;char s [N] ;//# define ZJC_LOCALint main ( ) {# ifdef ZJC_LOCAL freopen ( "in.txt", "r", stdin ) ;# endif int len ; gets ( s + 1 ) ; s [0] = '$', s [( len = strlen ( s + 1 ) ) + 1] = '$' ; S.build ( s, 0, len + 1 ) ; for ( register int m = read ( ) ; m ; -- m ) { static char opt ; while ( isspace ( opt = getchar ( ) ) ) ; if ( opt == 'Q' ) { int x ( read ( ) ), y ( read ( ) ) ; int l = 1, r = std :: min ( len - x + 1, len - y + 1 ), ans = 0, mid ; while ( l <= r ) { mid = ( l + r ) >> 1 ; if ( S.hashval ( x, x + mid - 1 ) == S.hashval ( y, y + mid - 1 ) ) ans = mid, l = mid + 1 ; else r = mid - 1 ; } printf ( "%d\n", ans ) ; continue ; } if ( opt == 'R' ) { int pos ( read ( ) ) ; char c ; while ( isspace ( c = getchar ( ) ) ) ; S.modify ( pos, c ) ; continue ; } int pos ( read ( ) ) ; char c ; while ( isspace ( c = getchar ( ) ) ) ; S.insert ( pos, c ) ; ++ len ; }}# undef N
改成unsigned int会快一秒多……
/************************************************************** Problem: 1014 User: Lazer2001 Language: C++ Result: Accepted Time:4132 ms Memory:6528 kb****************************************************************/# include <bits/stdc++.h>inline int read ( ) { register int x, c ; while ( isspace ( c = getchar ( ) ) ) ; for ( x = -48 + c ; isdigit ( c = getchar ( ) ) ; ( x *= 10 ) += c - 48 ) ; return x ;}# define N 101000static unsigned int hpow [N] ;class Splay { private : struct node { int siz ; char c ; unsigned int hval ; node *fa, *ch [2] ; inline void update ( ) { siz = ch [0] -> siz + ch [1] -> siz + 1 ; hval = ( 1u * hpow [( ch [1] -> siz + 1 )] * ch [0] -> hval + ( c - 'a' ) * hpow [ch [1] -> siz] + ch [1] -> hval ) ; // c - 'a'!!! } } pool [N << 1], *root, *null ; char* ss ; inline node* newnode ( node*& fa, unsigned int hval, char c ) { static node* tp ( pool + 1 ) ; tp -> siz = 1 ; tp -> hval = hval ; tp -> c = c ; return tp -> fa = fa, tp -> ch [0] = tp -> ch [1] = null, tp ++ ; } # define isrs( p ) ( p == p -> fa -> ch [1] ) inline void rotate ( node*& p ) { bool d ( isrs ( p ) ) ; node* par = p -> fa ; par -> ch [d] = p -> ch [! d] ; if ( p -> ch [! d] != null ) p -> ch [! d] -> fa = par ; if ( par -> fa != null ) par -> fa -> ch [isrs ( par )] = p ; p -> fa = par -> fa ; par -> fa = p ; p -> ch [! d] = par ; par -> update ( ) ; p -> update ( ) ; } inline void splay ( node* p, node* tar ) { while ( p -> fa != tar ) { if ( isrs ( p ) == isrs ( p -> fa ) && p -> fa -> fa != tar ) rotate ( p -> fa ) ; rotate ( p ) ; } if ( tar == null ) root = p ; } # undef isrs inline node* build ( node*& fa, int lf, int rg ) { if ( lf > rg ) return null ; int mid = ( lf + rg ) >> 1 ; node* p = newnode ( fa, ss [mid] - 'a', ss [mid] ) ; p -> ch [0] = build ( p, lf, mid - 1 ) ; p -> ch [1] = build ( p, mid + 1, rg ) ; p -> update ( ) ; return p ; } inline node* kth ( node*& p, int k ) { int cnt = p -> ch [0] -> siz ; if ( k == cnt + 1 ) return p ; return cnt < k ? kth ( p -> ch [1], k - p -> ch [0] -> siz - 1 ) : kth ( p -> ch [0], k ) ; } inline void display ( node* p ) { if ( p == null ) return ; display ( p -> ch [0] ) ; printf ( "%c %d ch [0] = %c, ch [1] = %c hval : %u\n", p -> c, p -> siz, p -> ch [0] -> c, p -> ch [1] -> c, p -> hval ) ; assert ( p -> siz == p -> ch [0] -> siz + p -> ch [1] -> siz + 1 ) ; display ( p -> ch [1] ) ; } public : Splay ( ) { null = pool ; null -> siz = 0 ; null -> hval = 0 ; null -> fa = null -> ch [0] = null -> ch [1] = null ; hpow [0] = 1 ; for ( int i = 1 ; i < N ; ++ i ) hpow [i] = hpow [i - 1] * 100137 ; } void build ( char* s, int lf, int rg ) { this -> ss = s ; root = build ( null, lf, rg ) ; } inline void insert ( int pos, char x ) { splay ( kth ( root, pos + 1 ), null ) ; splay ( kth ( root, pos + 2 ), root ) ; root -> ch [1] -> ch [0] = newnode ( root -> ch [1], x - 'a', x ) ; root -> ch [1] -> update ( ) ; root -> update ( ) ; } inline void modify ( int pos, char x ) { splay ( kth ( root, pos ), null ) ; splay ( kth ( root, pos + 2 ), root ) ; root -> ch [1] -> ch [0] -> hval = x - 'a' ; root -> ch [1] -> ch [0] -> c = x ; root -> ch [1] -> update ( ) ; root -> update ( ) ; } inline unsigned int hashval ( int lf, int rg ) { splay ( kth ( root, lf ), null ) ; splay ( kth ( root, rg + 2 ), root ) ; return root -> ch [1] -> ch [0] -> hval ; } inline void display ( ) { display ( root ) ; }} S ;char s [N] ;//# define ZJC_LOCALint main ( ) {# ifdef ZJC_LOCAL freopen ( "in.txt", "r", stdin ) ;# endif int len ; gets ( s + 1 ) ; s [0] = '$', s [( len = strlen ( s + 1 ) ) + 1] = '$' ; S.build ( s, 0, len + 1 ) ; for ( register int m = read ( ) ; m ; -- m ) { static char opt ; while ( isspace ( opt = getchar ( ) ) ) ; if ( opt == 'Q' ) { int x ( read ( ) ), y ( read ( ) ) ; int l = 1, r = std :: min ( len - x + 1, len - y + 1 ), ans = 0, mid ; while ( l <= r ) { mid = ( l + r ) >> 1 ; if ( S.hashval ( x, x + mid - 1 ) == S.hashval ( y, y + mid - 1 ) ) ans = mid, l = mid + 1 ; else r = mid - 1 ; } printf ( "%d\n", ans ) ; continue ; } if ( opt == 'R' ) { int pos ( read ( ) ) ; char c ; while ( isspace ( c = getchar ( ) ) ) ; S.modify ( pos, c ) ; continue ; } int pos ( read ( ) ) ; char c ; while ( isspace ( c = getchar ( ) ) ) ; S.insert ( pos, c ) ; ++ len ; }}# undef N
- BZOJ1014 火星人prefix Splay维护序列hash值+二分答案判LCP
- [BZOJ1014] [JSOI2008] 火星人prefix - splay + hash + 二分答案
- 【bzoj1014】[JSOI2008]火星人prefix splay+hash+二分
- 【平衡树维护序列+Hash求LCP】BZOJ1014(JSOI2008)[火星人prefix]题解
- BZOJ1014 火星人prefix (splay 哈希 二分答案)
- 【bzoj1014】【jsoi2008】【火星人prefix】【splay+hash】
- 【BZOJ1014】[JSOI2008]火星人prefix【Splay】【Hash】
- 【BZOJ1014】火星人prefix Splay 字符串Hash
- 【BZOJ1014】【tyvj3486】火星人prefix,Splay+字符串hash
- bzoj1014 [JSOI2008]火星人prefix ( splay + hash )
- [splay+二分+哈希] BZOJ1014: [JSOI2008]火星人prefix
- BZOJ 1014 火星人 prefix (splay hash 二分答案)
- 【BZOJ1014】【JSOI2008】火星人prefix Splay处理区间,hash+dichotomy(二分)check出解
- [BZOJ1014] [JSOI2008]火星人prefix && splay+字符串hash 重写版
- BZOJ1014 [JSOI2008]火星人prefix(Splay+字符串Hash)
- bzoj1014 火星人prefix 字符串hash + 区间splay树
- bzoj1014: [JSOI2008]火星人prefix splay
- [bzoj1014][splay][JSOI2008]火星人prefix
- ReactNative之刷新机制和界面间的数据传递
- 欢迎使用CSDN-markdown编辑器
- 623. Add One Row to Tree
- eclipse 构建web 项目
- 乱码问题总结
- BZOJ1014 火星人prefix Splay维护序列hash值+二分答案判LCP
- ###①Maven国内私服快速下载—阿里云+②maven向仓库添加依赖jar包 技巧:Maven中的settings.xml设置远程镜像库
- Matplotlib官方文档详解
- wangluoqingqiu diyipian
- 控制按钮隐藏
- 第五节 String类,subString,equals方法
- okHttp
- git&github使用问题和解决记录
- practise函数实现——乘法口诀表,判断素数,交换两数,判断闰年,数组的初始清空逆置