BZOJ-1014: [JSOI2008]火星人prefix(字符串HASH+splay)

题目:http://www.lydsy.com/JudgeOnline/problem.php?id=1014

这道题是有修改的,那么SA就不行了,想想之前那个字符串HASH的LCP求法,令hash(i,j)=s(j)27^0+s(j-1)27^1+...+s(i)*(j-i),那么如果hash(i,j)=hash(l,r),那么说明s(i..j)与s(l..r)有很高的概率相同,那么用splay维护hash,然后二分查找判定即可求出LCP。(虽然我不太喜欢字符串HASH这种不是100%的算法就是了,为了不被专门的数据卡WA,建议多取一两个HASH值进行比较)(这道题取26来乘就会WA。。。QaQ...)。

代码(觉得这种题还是递归版splay好写多了):

77094b36acaf2edd2f51958a8f1001e939019335.jpg.png
#include 

#include 

#include 

 

using namespace std ;

 

#define MAXN 300100

#define L( t ) left[ t ]

#define R( t ) right[ t ]

#define S( t ) size[ t ]

#define H( t ) Hash[ t ]

#define V( t ) value[ t ]

#define C( t )( t ==L(F( t )))

#define ULL unsigned long long

 

int getstr(char*s ){

    int len =0, ch ;

    for( ch =getchar(  );!( ch >='a'&& ch <='z'); ch =getchar(  ));

    s[++ len ]= ch ;

    for( ch =getchar(  ); ch >='a'&& ch <='z'; ch =getchar(  )) s[++ len ]= ch ;

    return len ;

}

 

char getchr(  ){

    int ch ;for( ch =getchar(  );!(( ch >='A'&& ch <='Z')||( ch >='a'&& ch <='z')); ch =getchar(  ));

    return ch ;

}

 

void getint(int&t ){

    int ch ;for( ch =getchar(  );!( ch >='0'&& ch <='9'); ch =getchar(  ));

    t = ch -'0';

    for( ch =getchar(  ); ch >='0'&& ch <='9'; ch =getchar(  )){

        t *=10, t += ch -'0';

    }

}

 

void putint(int t ){

    if(! t )putchar('0');else{

        int ans[20]; ans[0]=0;

        for(; t ; t /=10) ans[++ ans[0]]= t %10;

        for(int i = ans[0]; i ; i --)putchar('0'+ ans[ i ]);

    }

    putchar('\n');

}

 

int left[ MAXN ], right[ MAXN ], size[ MAXN ];

ULL Hash[ MAXN ], value[ MAXN ], Exp[ MAXN ];

int roof =0, V =0;

 

void update(int t ){

    S( t )=S(L( t ))+S(R( t ))+1;

    H( t )=H(R( t ));

    H( t )+=V( t )* Exp[S(R( t ))];

    H( t )+=H(L( t ))* Exp[S(R( t ))+1];

}

 

void zag(int&t ){

    int k =R( t );

    R( t )=L( k );update( t );

    L( k )= t ;update( k );

    t = k ;

}

 

void zig(int&t ){

    int k =L( t );

    L( t )=R( k );update( t );

    R( k )= t ;update( k );

    t = k ;

}

 

bool splay(int r ,int&t ,bool flag ){

    if(S(L( t ))== r )return true;

    bool w =splay( r  y )swap( x , y );

    int len =S( roof )-2;

    int l =0, r = len - y +2;

    while( r - l >1){

        int mid =( l + r )>>1;

        if(cp( x , x + mid -1)==cp( y , y + mid -1)) l = mid ;else r = mid ;

    }

    return l ;

}

 

int main(  ){

    n =getstr( s );getint( m );

    Init(  );

    while( m --){

        char c =getchr(  );

        if( c =='Q'){

            int x , y ;getint( x ),getint( y );

            putint(Query( x , y ));

        }else if( c =='R'){

            int x ;getint( x ); c =getchr(  );

            splay( x , roof ,true);

            V( roof )= c -'0';

            update( roof );

        }else{

            int x ;getint( x ); c =getchr(  );

            splay( x , roof ,true);

            splay(0,R( roof ),true);

            Insert(int( c )-int('0'),L(R( roof )));

            update(R( roof ));update( roof );

        }

    }

    return 0;

}

你可能感兴趣的:(BZOJ-1014: [JSOI2008]火星人prefix(字符串HASH+splay))