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
阅读全文
0 0