BZOJ1014 火星人prefix Splay维护序列hash值+二分答案判LCP
2017-11-27 10:37
453 查看
大家都很强, 可与之共勉。
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 101000 static unsigned long long hpow ; 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 ; //# define ZJC_LOCAL int 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 101000 static unsigned int hpow ; 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 ; //# define ZJC_LOCAL int 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
相关文章推荐
- 【BZOJ】1014: [JSOI2008]火星人prefix(splay+hash+二分+lcp)
- BZOJ 1014 JSOI 2008 火星人prefix Splay维护字符串Hash + 二分
- BZOJ_1014_[JSOI2008]_火星人prefix_(Splay+LCP_Hash+二分)
- 【平衡树维护序列+Hash求LCP】BZOJ1014(JSOI2008)[火星人prefix]题解
- BZOJ1014 火星人prefix (splay 哈希 二分答案)
- bzoj 1014: [JSOI2008]火星人prefix(splay维护区间+Hash+二分)
- BZOJ 1014 火星人 prefix (splay hash 二分答案)
- 【BZOJ1014】【JSOI2008】火星人prefix Splay处理区间,hash+dichotomy(二分)check出解
- bzoj1014 [JSOI2008]火星人prefix(二分答案+哈希+平衡树)
- 【BZOJ1014】【JSOI2008】火星人prefix Splay处理区间,hash+dichotomy(二分)check出解
- [BZOJ]1014: [JSOI2008]火星人prefix splay+hash+二分
- 【bzoj1014】[JSOI2008]火星人prefix splay+hash+二分
- [bzoj1014](JSOI2008)火星人 prefix (Splay维护哈希)
- BZOJ 1014 JSOI2008 火星人prefix Splay+Hash+二分
- BZOJ 1014 JSOI2008 火星人prefix Splay+Hash+二分
- BZOJ 1014 [JSOI2008]火星人prefix | Splay维护哈希值
- [bzoj1014][JSOI2008]火星人prefix【splay】【哈希】【二分】
- BZOJ 1014: [JSOI2008]火星人prefix [splay 二分+hash] 【未完】
- BZOJ 1014 [JSOI2008]火星人prefix (Splay + Hash + 二分)
- bzoj1014: [JSOI2008]火星人prefix(splay+hash+二分)