BZOJ 1014 [JSOI2008] Martian prefix

+ + Binary string the Hash balanced tree (fhq_treap)

And changing operation is not inserted characters, the string is treated Hash value of the LCP

$ Prefix is ​​the first process out the hash value of the original $ string, then the position of the start of the two-half the length of the LCP enumeration

Then the process is the use of prefixes and $ l $, $ hash $ $ R & lt interval value $, compared to

But this question has operations insert and change the character of

Then you need to maintain $ hash $ value of the string with a balanced tree

The whole problem to use to balance the tree is to find $ hash $ value for a range

Then the following standard established a balanced tree, each node records for the node and its subtree hash value

So a $ hash $ node is directly

$hash_{rson}+base^{size[rson]}*ch+base^{size[rson]+1}*hash_{lson}$

Here it is fhq_treap with maintenance of the entire string $ hash $ value

#include <bits/stdc++.h>
#define base 131
using namespace std;
const int MAXN=101000;
int m,root,tot,len;
char g[MAXN];
int z[MAXN];
struct node
{
    int ha;
    char c;
    int son[2],si,key;
}sh[MAXN];
int newnode(char ch)
{
    tot++;
    sh[tot].c=ch;
    sh[tot].ha=(int)ch;
    SH [TOT] .si = . 1 ; 
    SH [TOT] .key = RAND ();
     return TOT; 
} 
void a pushup ( int X) 
{ 
    SH [X] .si = SH [SH [X] .son [ 0 ]] SH + .si [SH [X] .son [ . 1 ]] + Si. . 1 ; 
    SH [X] .ha = SH [SH [X] .son [ . 1 ]] HA + Z [SH [SH [X].. Son [ . 1 ]]. Si] * ( int ) SH [X] .c + Z [SH [SH [X] .son [ . 1 ]]. Si + . 1 ] * SH [SH [X] .son [ 0 ]] .ha; // current node maintains hash 
} 
int Build ( int LL, int RR) 
{
    int mid,cur;
    mid=(ll+rr)>>1;
    cur=newnode(g[mid]);
    if (ll==rr)
    {
        pushup(cur);
        return cur;
    }
    if (ll<=mid-1)
      sh[cur].son[0]=build(ll,mid-1);
    if (mid+1<=rr)
      sh[cur].son[1]=build(mid+1,rr);
    pushup(cur);
    return cur;
}
void split(int now, now;int k, int & X, int & Y) // fhq_treap basic operation of the k-th divided here to 
{ 
    IF (now == 0 ) 
    { 
        X = 0 ; 
        Y = 0 ;
         return ; 
    } 
    IF (SH [SH [now ] .son [ 0 .]] Si> = K) 
    { 
        Y = now; 
        Split (SH [now] .son [ 0 ], K, X, SH [now] .son [ 0 ]); 
    } 
    the else 
    { 
        X = 
        Split (SH [now] .son [ 1],k-1-sh[sh[now].son[0]].si,sh[now].son[1],y);
    }
    pushup(now);
}
int merge(int x,int y)
{
    if (x==0)
      return y;
    if (y==0)
      return x;
    if (sh[x].key<=sh[y].key)
    {
        sh[x].son[1]=merge(sh[x].son[1],y);
        pushup(x);
        return x;
    }
    else
    {
        sh[y].son[0]=merge(x,sh[y].son[0]);
        pushup(y);
        return y;
    }
}
void insert(int k,char ch)
{
    int a,b;
    split(root,k,a,b);
    root=merge(merge(a,newnode(ch)),b);
}
void del(int k)
{
    int a,b,c;
    split(root,k,a,b);
    split(a,k-1,a,c);
    c=merge(sh[c].son[0],sh[c].son[1]);
    the root=Merge (Merge (A, B), C); 
} 
void Change ( int K, char CH) 
{ 
    int A, B, C; 
    Split (the root, K - . 1 , A, B); 
    Split (B, . 1 , B , C); 
    SH [B] .c = CH; 
    SH [B] .ha = ( int ) CH; 
    the root = Merge (A, Merge (B, C)); 
} 
int  GET ( int L, int R & lt) / / calculated hash value for a range 
{ 
    int a, B, C; 
    Split (the root, L - . 1 , a, B); 
    Split (B, R & lt -l +1,b,c);
    int h;
    h=sh[b].ha;
    b=merge(b,c);
    root=merge(a,b);
    return h;
}
int query(int x,int y)
{
    if (get(x,x)!=get(y,y))
      return 0;
    int l,r;
    l=0;r=min(len-x+1,len-y+1);
    while (l<r)//二分查找答案
    {
        int mid;
        mid=l+((r-l+1)>>1);
        if (get(x,x+mid-1)==get(y,y+mid-1))
          l=mid;
        else
          r=mid-1;
    }
    return l;
}
int main()
{
    srand(time(0));
    scanf("%s",g+1);
    len=strlen(g+1);
    z[0]=1;
    for (int i=1;i<=100000;i++)
      z[i]=z[i-1]*base;
    root=build(1,len);
    scanf("%d",&m);
    for (int i=1;i<=m;i++)
    {
        char op[3];
        scanf("%s",op);
        if (op[0]=='Q')
        {
            int x,y;
            scanf("%d%d",&x,&y);
            printf("%d\n",query(x,y));
        }
        if (op[0]=='R')
        {
            int x;
            char d[5];
            scanf("%d%s",&x,d);
            change(x,d[0]);
        }
        if (op[0]=='I')
        {
            int x;
            char d[5];
            scanf("%d%s",&x,d);
            insert(x,d[0]);
            len++;
        }
    }
}

 

Guess you like

Origin www.cnblogs.com/huangchenyan/p/11331591.html