BZOJ 1014 [Martian prefix]

Face questions

The meaning of problems

  Maintain a string, support the insertion of a character, a character modification, the longest common prefixes and suffixes required two.

answer

  Maintenance string balanced trees, each additional node maintains a child node of the tree represents the hash value of the string. Splay chosen as a balanced tree implementations when writing this question, this time to maintain node information only when every one rotation of the hash value of the update associated sub-tree node can guarantee correct.

  Equation string using the hash \ (hash (s) = ( \ sum_ {i = 1} ^ {| s |} (id (s_i) -96) \ cdot 31 ^ {| s | -i}) \ mod 2 ^ {64} \) (where \ (96 \) is 'a' ASCII codes \ (- 1 \) , \ (31 \) and \ (2 ^ {64} \) may be any readily conflict hash multiplier and modulus), may be succinctly with left and right subtrees of the tree is obtained hash value may be by \ (hash (s_ {i \ dots j}) = hash (s_ {1 \ dots j}) - 31 ^ { j-i + 1} \ cdot hash (s_ {1 \ dots i-1}) \ mod 2 ^ {64} \) is determined at any of the prefix string of the hash value string substring hash value, and the first character after the prefix just need to find a hash value prefix string rotation to the root node Splay tree, in which case a hash value of the root prefix of the left subtree is the Ha Greek values. When seeking to prevent the hash value of the entire string error in the extra addition of one end of the string '$' character.

  Updated node in the subtree associated hash value modification operation just after insertion and rotation place related to the root node, once modified. The answer can be bipartite, each corresponding to two sub-inspection when evaluated longest common prefix string \ (hash (s_ {x \ dots x + m}), hash (s_ {y \ dots y + m}) \) are the same.


Code

#include<iostream>
#include<cstdio>
#include<cstring>
#include<vector>
using namespace std;
typedef unsigned long long ull;
const int maxn=1e5+5;
const ull mul=31;
vector<ull> powarr;
ull getpow(int n){
    while (powarr.size()<=n)
        powarr.push_back(powarr.back()*mul);
    return powarr[n];
}
struct Splay_Tree{
    struct node{
        node *fa,*ch[2];
        char val;
        int size;
        ull hash;
    };
    node *root;
    node *const nil;
    node *nnode(char ch){
        node *nd=new node();
        nd->fa=nd->ch[0]=nd->ch[1]=nil;
        nd->val=ch; nd->size=1; nd->hash=nd->val-'a'+1;
        return nd;
    }
    Splay_Tree():nil(new node()){
        nil->fa=nil->ch[0]=nil->ch[1]=nil;
        nil->val=0; nil->size=0; nil->hash=0;
        root=nnode('$');
    }
    int size(){ return root->size-1; }
    void update(node *nd){
        nd->size=0; nd->hash=0;
        nd->size+=nd->ch[0]->size;
        nd->hash*=getpow(nd->ch[0]->size);
        nd->hash+=nd->ch[0]->hash;
        nd->size+=1;
        nd->hash*=mul;
        nd->hash+=nd->val-'a'+1;
        nd->size+=nd->ch[1]->size;
        nd->hash*=getpow(nd->ch[1]->size);
        nd->hash+=nd->ch[1]->hash;
    }
    bool getid(node *u){
        return u==u->fa->ch[1];
    }
    void rotate(node *u){
        node *v,*w,*x;
        bool b,c;
        if (u==nil) return;
        v=u->fa;
        if (v==nil) return;
        b=getid(u); c=getid(v);
        w=v->fa; x=u->ch[!b];
        v->ch[b]=x; if (x!=nil) x->fa=v;
        u->ch[!b]=v; v->fa=u;
        if (w!=nil) w->ch[c]=u; u->fa=w;
        update(v); update(u);
    }
    void splay(node *u){
        while (u->fa->fa!=nil){
            if (getid(u)==getid(u->fa)){
                rotate(u->fa); rotate(u);
            }
            else {
                rotate(u); rotate(u->fa);
            }
        }
        if (u->fa!=nil) rotate(u);
        root=u;
    }
    void find(int x){
        node *u=root;
        bool b;
        while (true){
            b=x>u->ch[0]->size;
            x-=b?u->ch[0]->size+1:0;
            if (!x) break;
            u=u->ch[b];
        }
        splay(u);
    }
    ull query(int x){
        find(x+1);
        return root->ch[0]->hash;
    }
    ull hash(int x,int y){
        return query(y)-query(x)*getpow(y-x);
    }
    void change(int x,char ch){
        find(x);
        root->val=ch;
        update(root);
    }
    void insert(int x,char ch){
        find(x+1);
        node *u,*v,*w;
        u=nnode(ch);
        v=root->ch[0];
        w=root;
        u->ch[0]=v;
        if (v!=nil) v->fa=u;
        u->ch[1]=w;
        w->fa=u;
        w->ch[0]=nil;
        update(w);
        update(u);
        root=u;
    }
};
Splay_Tree tree;
char s[maxn],a[10],b[10];
int query(int x,int y){
    int l,r,m;
    l=0; r=tree.size()-y+2;
    while (r-l>1){
        m=(l+r)/2;
        if (tree.hash(x-1,x+m-1)==tree.hash(y-1,y+m-1))
            l=m;
        else r=m;
    }
    return l;
}
int main(){
    int i,m,x,y;
    powarr.clear(); powarr.push_back(1);
    scanf("%s",s);
    for (i=strlen(s)-1;i>=0;i--)
        tree.insert(0,s[i]);
    scanf("%d",&m);
    while (m--){
        scanf("%s",a);
        switch (a[0]){
        case 'Q':
            scanf("%d%d",&x,&y);
            if (x>y) swap(x,y);
            printf("%d\n",query(x,y));
            break;
        case 'R':
            scanf("%d%s",&x,b);
            tree.change(x,b[0]);
            break;
        case 'I':
            scanf("%d%s",&x,b);
            tree.insert(x,b[0]);
            break;
        }
    }
    return 0;
}

Guess you like

Origin www.cnblogs.com/Kilo-5723/p/12189932.html