您的位置:首页 > 运维架构

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
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: