acdream1104 瑶瑶想找回文串

来源:互联网 发布:写漫画的软件 编辑:程序博客网 时间:2024/06/05 07:32

瑶瑶想找回文串

Time Limit: 20000/10000MS (Java/Others)Memory Limit: 256000/128000KB (Java/Others)
SubmitStatisticNext Problem

Problem Description

刚学完后缀数组求回文串的瑶瑶(tsyao)想到了另一个问题:如果能够对字符串做一些修改,怎么在每次询问时知道以某个字符为中心的最长回文串长度呢?因为瑶瑶整天只知道LOL,当他知道自己省选成绩的时候就天天在LOL,导致现在的她实在是太弱了,根本解决不了这个问题,于是就来找你帮忙,么么哒~你就帮帮她吗

Input

第一行为一个长度不超过100000字符串s作为初始字符串。第二行一个正整数n,表示操作/询问的个数。接下来n行,每行有如下几种可能出现的操作/询问:

Insert a x  在a处字符的后面插入一个字符x

Delete a  把a处字符删除

Update a x 把a处字符改为x

Query a 查询以a为中心的最长回文串长度

Output

对于每个询问,输出得到的最长回文串长度

Sample Input

baaaaab5Query 4Delete 2Query 3Delete 4Query 3

Sample Output

735

Hint

对于100%的数据 1<=n<=50000,字符串仅包含小写字母,保证操作过程中字符串长度不超过150000  (hint:请各位大胆写)

单组输入,共10组数据。

Source

zslzx

Manager

tsyao
二分+字符串哈希+splay;
#include<cstdio>#include<iostream>#include<algorithm>#include<cstring>#include<queue>#include<ctime>#include<map>#include<set>#include<stack>#include<list>#define maxn 200010#define LL long long#define u64 unsigned long long#define yy 133using namespace std ;int num[maxn];u64 bit[maxn];struct node {    int size ;    int ch[2];    int pra;    u64 lsum,rsum,val;    void init( int tt ) {        ch[0] = ch[1] = 0;        size = 1;        lsum = rsum = val = tt ;    }} tree[maxn];int len;int root;char a[maxn];int n, m;int getSize(int x) {    if (x) return tree[x].size;    return 0;}u64 getlsum( int x ){    if(x) return tree[x].lsum ;    return 0 ;}u64 getrsum( int x ){    if(x) return tree[x].rsum ;    return 0 ;}void update(int x) {    tree[x].size = 1 + getSize(tree[x].ch[0]) + getSize(tree[x].ch[1]);    tree[x].lsum = tree[x].val*bit[getSize(tree[x].ch[0])] + getlsum(tree[x].ch[0])    +getlsum(tree[x].ch[1])*bit[getSize(tree[x].ch[0])+1] ;    tree[x].rsum = tree[x].val*bit[getSize(tree[x].ch[1])] + getrsum(tree[x].ch[1])    +getrsum(tree[x].ch[0])*bit[getSize(tree[x].ch[1])+1] ;}void build( int &x , int s , int e , int f ){    if(s>e) return ;    int mid = (s+e)>>1 ;    x = ++len ;    tree[x].pra = f ;    tree[x].init(num[mid]) ;    build(tree[x].ch[0],s,mid-1,x) ;    build(tree[x].ch[1],mid+1,e,x) ;    update(x) ;}void init(){    int i , k , l ;    len = 0 ;    tree[0].pra = -1 ;    tree[0].init(-1) ;    for( i = 1 ; i <= n ;i++){       num[i] = a[i-1]-'a'+1;    }    num[0] = num[n+1] = -1 ;    build( tree[0].ch[1] , 0 , n+1 , 0 ) ;}void rotate(int x , int d ){    int p = tree[x].pra ;    tree[p].ch[d] = tree[x].ch[d^1] ;    tree[tree[x].ch[d^1]].pra = p ;    tree[x].ch[d^1] = p ;    int g = tree[p].pra ;    tree[p].pra = x ;    if( g != -1 )        tree[g].ch[p == tree[g].ch[1]] = x ;    tree[x].pra = g ;    //更新值    tree[x].size = tree[p].size ;    update(p) ;    return ;}void splay( int &x , int f ){    while( tree[x].pra != f )    {        int p = tree[x].pra ;        if(tree[p].pra == f )        {            if( tree[p].ch[0] == x ) rotate(x,0) ;            else rotate(x,1) ;        }        else        {            int g = tree[p].pra ;            if( tree[g].ch[0] == p )            {                if( tree[p].ch[0] == x )                    rotate(p,0),rotate(x,0) ;                else rotate(x,1),rotate(x,0) ;            }            else{                if( tree[p].ch[1] == x )                    rotate(p,1),rotate(x,1) ;                else rotate(x,0),rotate(x,1) ;            }        }    }    update(x) ;}void select( int k , int f ){    int x = tree[0].ch[1] ;    while( k != getSize(tree[x].ch[0])+1)    {        if( k <= getSize(tree[x].ch[0]))        {            x = tree[x].ch[0] ;        }        else        {            k -= 1+getSize(tree[x].ch[0]) ;            x = tree[x].ch[1] ;        }    }    splay(x,f) ;}void cut(){    int a, b , c , i ;    scanf("%d" , &a) ;    b = a ;    select(a,0) ;    root = tree[0].ch[1] ;    select(b+2,root) ;    int tmp = tree[tree[root].ch[1]].ch[0] ;    n-- ;    tree[tree[root].ch[1]].ch[0] = 0 ;    update(tree[root].ch[1]) ;    update(root) ;}void replace(){    int a, b , i ;    char c[2];    scanf("%d%s" , &a,c ) ;    b = a ;    select(a,0) ;    root = tree[0].ch[1] ;    select(b+2,root) ;    int tmp = tree[tree[root].ch[1]].ch[0] ;    tree[tmp].init(c[0]-'a'+1) ;    update(tree[root].ch[1]) ;    update(root) ;}void insert(){    int a, b , i ;    char c[2];    scanf("%d%s" , &a,c ) ;    select(a+1,0) ;    root = tree[0].ch[1] ;    select(a+2,root) ;    n++;    int tmp = ++len ;    tree[tmp].init(c[0]-'a'+1) ;    tree[tree[root].ch[1]].ch[0] = tmp ;    tree[tmp].pra = tree[root].ch[1] ;    update(tree[root].ch[1]) ;    update(root) ;}bool check(int k,int mid){    select(k-mid,0) ;    root = tree[0].ch[1] ;    select(k+mid+2,root) ;    int tmp = tree[tree[root].ch[1]].ch[0] ;    return tree[tmp].lsum == tree[tmp].rsum ;}int main(){    int i,k ;    int L,R,mid,ans;    u64 u,v;    char str[20] ;    bit[0]=1;    for( i = 1 ; i < maxn-10 ;i++)        bit[i]=bit[i-1]*yy;    while(scanf("%s",a) != EOF)    {        n = strlen(a) ;        init();        scanf("%d",&m) ;        while(m--)        {            scanf("%s",str) ;            if(str[0]=='I')            {                insert();            }            else if(str[0]=='D')            {                cut();            }            else if(str[0]=='U')            {                replace();            }            else{                ans=0;                scanf("%d",&k);                L=0;R=min(k-1,n-k);                while(L<R)                {                    mid=(L+R+1)>>1 ;                    if(check(k,mid))                    {                        ans=mid;                        L=mid;                    }                    else R = mid-1;                }                printf("%d\n",ans*2+1);            }        }    }    return 0 ;}


0 0