• BZOJ 1014 火星人 | 平衡树维护哈希


    BZOJ 1014 火星人

    题意

    有一个字符串,三中操作:在某位置后面插入一个字符、修改某位置的字符、询问两个后缀的最长公共前缀。

    题解

    看到网上的dalao们都说这道题是平衡树,我就很懵x……平衡树维护什么啊?
    最后发现某个节点维护的是它所代表的区间的哈希值——显然这个哈希值可以从左右子树的哈希值和这个节点上的字符算出来。

    #include <cstdio>
    #include <cmath>
    #include <cstring>
    #include <algorithm>
    #define space putchar(' ')
    #define enter putchar('
    ')
    using namespace std;
    typedef unsigned long long ll;
    template <class T>
    void read(T &x){
        char c;
        bool op = 0;
        while(c = getchar(), c < '0' || c > '9')
    	if(c == '-') op = 1;
        x = c - '0';
        while(c = getchar(), c >= '0' && c <= '9')
    	x = x * 10 + c - '0';
        if(op) x = -x;
    }
    template <class T>
    void write(T x){
        if(x < 0) putchar('-'), x = -x;
        if(x >= 10) write(x / 10);
        putchar('0' + x % 10);
    }
    const int N = 100005, B = 29;
    int n, m;
    int idx, root, fa[N], ls[N], rs[N], val[N], sze[N];
    ll hsh[N], pw[N];
    char s[N];
    #define which(x) (ls[fa[(x)]] == (x))
    void upt(int u){
        sze[u] = sze[ls[u]] + sze[rs[u]] + 1;
        hsh[u] = hsh[ls[u]] + val[u] * pw[sze[ls[u]]] + hsh[rs[u]] * pw[sze[ls[u]] + 1];
    }
    void rotate(int u){
        int v = fa[u], w = fa[v], b = which(u) ? rs[u] : ls[u];
        if(w) which(v) ? ls[w] = u : rs[w] = u;
        which(u) ? (ls[v] = b, rs[u] = v) : (rs[v] = b, ls[u] = v);
        fa[u] = w, fa[v] = u;
        if(b) fa[b] = v;
        upt(v), upt(u);
    }
    void splay(int u, int tar){
        while(fa[u] != tar){
            if(fa[fa[u]] != tar){
                if(which(u) == which(fa[u])) rotate(fa[u]);
                else rotate(u);
            }
            rotate(u);
        }
        if(!tar) root = u;
    }
    int build(int l, int r, int pre){
        if(l > r) return 0;
        int u = ++idx, mid = (l + r) >> 1;
        val[u] = s[mid] - 'a' + 1, fa[u] = pre;
        ls[u] = build(l, mid - 1, u);
        rs[u] = build(mid + 1, r, u);
        upt(u);
        return u;
    }
    int find(int x){
        int u = root;
        while(sze[ls[u]] != x)
            if(x <= sze[ls[u]] - 1) u = ls[u];
            else x -= sze[ls[u]] + 1, u = rs[u];
        return u;
    }
    void insert(int pos, int x){
        int u = find(pos), v = find(pos + 1);
        splay(u, 0), splay(v, u);
        ls[v] = ++idx, fa[idx] = v, val[idx] = x, sze[idx] = 1;
        splay(idx, 0);
    }
    void change(int pos, int x){
        int u = find(pos);
        val[u] = x;
        splay(u, 0);
    }
    ll gethsh(int pos, int len){
        int u = find(pos - 1), v = find(pos + len);
        splay(u, 0), splay(v, u);
        return hsh[ls[v]];
    }
    int query(int a, int b){
        int l = 0, r = sze[root] - max(a, b) - 1, mid;
        while(l < r){
            mid = (l + r + 1) >> 1;
            if(gethsh(a, mid) == gethsh(b, mid)) l = mid;
            else r = mid - 1;
        }
        return l;
    }
    int main(){
        scanf("%s", s + 1);
        n = strlen(s + 1);
        pw[0] = 1;
        for(int i = 1; i < N; i++)
            pw[i] = pw[i - 1] * B;
        root = build(0, n + 1, 0);
        read(m);
        while(m--){
            char op[2];
            scanf("%s", op);
            if(op[0] == 'Q'){
                int a, b;
                read(a), read(b);
                write(query(a, b)), enter;
            }
            else if(op[0] == 'I'){
                int pos;
                scanf("%d%s", &pos, op);
                insert(pos, op[0] - 'a' + 1);
            }
            else if(op[0] == 'R'){
                int pos;
                scanf("%d%s", &pos, op);
                change(pos, op[0] - 'a' + 1);
            }
        }
        return 0;
    }
    
  • 相关阅读:
    AutoMapper,对象映射的简单使用
    Angular 4.0从入门到实战
    IE报错:The given path's format is not supported
    原生js中slice()方法和splice()区别
    使用jquery插件ajaxfileupload一次上传多个文件,示例
    C#路径中获取文件全路径、目录、扩展名、文件名称
    NET二进制图片存储与读取的常见方法,iTextSharp添加图片生成PDF文件
    Type.GetType()反射另外项目中的类时返回null的解决方法
    C#中对于Enum类型的遍历
    读取word到二进制,再转成word
  • 原文地址:https://www.cnblogs.com/RabbitHu/p/BZOJ1014.html
Copyright © 2020-2023  润新知