zoj3533 Gao the String I(splay)

来源:互联网 发布:软件项目管理期末试卷 编辑:程序博客网 时间:2024/05/22 14:15

题目链接:zoj3533 Gao the String I

题意:其实就是维护一个数列。有四个操作,reverse和modify就是常见的splay操作,lcp(i,j)操作,表示求后缀i,j的最长公共前缀,palindrome是求整个串的最长回文串。

解题思路:首先我们要搞清楚的是要维护什么,palindrome操作因为只有10个,所以这个是可以暴力做的。那么关键的是怎么求lcp了,没什么好的办法,hash+二分吧,所以这里维护的就是一段区间的hash值了,因为有reverse操作,所以要维护正反两个hash值,reverse的时候,swap之即可。palindrome的话,就是按先序遍历,把字符串读出来,然后用manacher算法搞一遍就ok了(manacher算法,百度之。。有好多文章都写的好详细),不会manacher的话,用后缀数组也可搞,用hash+二分也可搞。总之他只有十个操作,所以暴力之即可。

代码:

#include <stdio.h>#include <string.h>#include <algorithm>#include <map>#include <math.h>#include <queue>#include <vector>#include <string>#include <iostream>#include <stdlib.h>#include <time.h>#define lowbit(x) (x&(-x))#define ll long long#define ull unsigned long long#define lson l , m , rt << 1#define rson m + 1 , r , rt << 1 | 1#define ls son[0][rt]#define rs son[1][rt]#define new_edge(a,b,c) edge[tot].t = b , edge[tot].v = c , edge[tot].next = head[a] , head[a] = tot ++using namespace std;const int maxn = 111111 ;int son[2][maxn] , fa[maxn] , size[maxn] , col[maxn] ;char s[maxn] ;ull val[maxn] , sum[maxn] , hash_value[2][maxn] ;ull x = 127 , p[maxn] ;void new_node ( ull _val , int rt ) {if ( !rt ) return ;col[rt] = ls = rs = fa[rt] = sum[rt] = 0 ;val[rt] = _val ;size[rt] = 1 ;}void push_up ( int rt ) {size[rt] = size[ls] + size[rs] + 1 ;sum[rt] = sum[rs] * p[size[ls]+1] + val[rt] * p[size[ls]] + sum[ls] ;hash_value[0][rt] = hash_value[0][rs] * p[size[ls]+1] + val[rt] * p[size[ls]] + hash_value[0][ls] ;hash_value[1][rt] = hash_value[1][ls] * p[size[rs]+1] + val[rt] * p[size[rs]] + hash_value[1][rs] ;}void reverse ( int rt ) {if ( !rt ) return ;col[rt] ^= 1 ;swap ( ls , rs ) ;swap ( hash_value[0][rt] , hash_value[1][rt] ) ;sum[rt] = hash_value[0][rt] ;}void push_down ( int rt ) {if ( col[rt] ) {reverse ( ls ) ; reverse ( rs ) ;col[rt] = 0 ;}}void down ( int rt ) {if ( fa[rt] ) down ( fa[rt] ) ;push_down ( rt ) ;}void rot ( int rt ) {int y = fa[rt] , z = fa[y] , c = rt == son[0][y] ;son[!c][y] = son[c][rt] , fa[son[c][rt]] = y ;son[c][rt] = y , fa[y] = rt ;fa[rt] = z ;son[y==son[1][z]][z] = rt ;push_up ( y ) ;}void splay ( int rt , int to ) {down ( rt ) ;while ( fa[rt] != to ) {int y = fa[rt] , z = fa[y] ;if ( z != to ) rot ( (rt==son[0][y])^(y==son[0][z]) ? rt : y ) ;rot ( rt ) ;}push_up ( rt ) ;}int build ( int l , int r ) {if ( l > r ) return 0 ;int rt = ( l + r ) >> 1 ;new_node ( (ull)s[rt-1] , rt ) ;ls = build ( l , rt - 1 ) ; fa[ls] = rt ;rs = build ( rt + 1 , r ) ; fa[rs] = rt ;push_up ( rt ) ;return rt ;}int cnt ( int rt , int k ) {push_down ( rt ) ;if ( size[ls] + 1 == k ) return rt ;if ( size[ls] >= k ) return cnt ( ls , k ) ;return cnt ( rs , k - size[ls] - 1 ) ;}int rad[maxn<<2] , s1[maxn<<2] , tot ;void gao ( int rt ) {if ( !rt ) return ;push_down ( rt ) ;gao ( ls ) ;s[tot++] = (int) val[rt] ;gao ( rs ) ;}int Pal ( int n  , int rt ) {int i , j , k , len = 2 ;tot = 0 ;gao ( rt ) ;s1[0] = '$' , s1[1] = '#' ;for ( i = 1 ; i <= n ; i ++ ) s1[len++] = (int)s[i] , s1[len++] = '#' ;int id = 0 , mx = 0 , ans = 0 ;rad[0] = 1 ;for ( i = 1 ; i < len ; i ++ ) {if ( mx >= i ) rad[i] = min ( rad[2*id-i] , mx - i ) ;else rad[i] = 1 ;while ( s1[i+rad[i]] == s1[i-rad[i]] ) rad[i] ++ ;if ( rad[i] + i - 1 > mx ) mx = rad[i] + i - 1 , id = i ;ans = max ( ans , rad[i] - 1 ) ;}return ans ;}ull get ( int l , int r , int &rt ) {l -- , r ++ ;l = cnt ( rt , l ) ; r = cnt ( rt , r ) ;splay ( l , 0 ) ;splay ( r , l ) ;rt = l ;return sum[son[0][r]] ;}int Lcp ( int a , int b , int n , int &rt ) {a ++ , b ++ ; n ++ ;int l = 1 , r = n - max ( a , b ) + 1 ;while ( l <= r ) {int m = ( l + r ) >> 1 ;ull t1 = get ( a , a + m - 1 , rt ) , t2 = get ( b , b + m - 1 , rt ) ;if ( t1 == t2 ) l = m + 1 ;else r = m - 1 ;}return r ;}int Reverse ( int l , int r , int rt ) {    l -- , r ++ ;l = cnt ( rt , l ) ; r = cnt ( rt , r ) ;splay ( l , 0 ) ;splay ( r , l ) ;reverse ( son[0][r] ) ;push_up ( r ) ; push_up ( l ) ;return l ;}int Modify ( int p , ull _val , int rt ) {p ++ ;p = cnt ( rt , p ) ;splay ( p , 0 ) ;val[p] = _val ;push_up ( p ) ;return p ;}int main() {int i , j , k , n , m , q ;p[0] = 1 ;for ( i = 1 ; i < maxn ; i ++ ) p[i] = p[i-1] * x ;while ( scanf ( "%s" , s + 1 ) != EOF ) {n = strlen ( s + 1 ) ;s[0] = s[n+1] = s[n+2] = 0 ;int rt = build ( 1 , n + 2 ) ;scanf ( "%d" , &m ) ;while ( m -- ) {char op[22] ;int a , b ;scanf ( "%s" , op ) ;if ( op[0] == 'L' ) {scanf ( "%d%d" , &a , &b ) ;printf ( "%d\n" , Lcp ( a , b , n , rt ) ) ;} else if ( op[0] == 'P' ) printf ( "%d\n" , Pal ( n , rt ) ) ;else if ( op[0] == 'R' ) {scanf ( "%d%d" , &a , &b ) ;a ++ , b ++ ;rt = Reverse ( a , b , rt ) ;}else {scanf ( "%d%s" , &a , op ) ;rt = Modify ( a , op[0] , rt ) ;}tot = 0 ; }}return 0;}


5 2
原创粉丝点击