题意:其实就是维护一个数列。有四个操作,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;
}