• bzoj1014


    splay+二分+哈希

    splay维护区间哈希值,每次二分长度

    调了很长时间,主要是两个错误:1.提取区间应该是pos+1,pos+2,因为现在在开头放了一个?,所以现在应该是位置比pos+1大,比pos+2小 2.二分边界,因为多加了两个字符,所以原串长度应该是cnt-2,那么二分边界应该是-1->len+1,也就是-1>cnt-y,因为cnt=n+2,串的最大长度应该小于结尾,所以y+len-1<=n,y+len-1<=cnt-2,所以应该是len<=cnt-y-1,又因为二分边界应该比上界大一,所以是cnt-y

    原先的姿势太丑陋了,就新抄了个模板

    #include<bits/stdc++.h>
    using namespace std;
    const int N = 400010;
    const int seed = 19992147;
    int n, root, m;
    int pw[N];
    char s[N];
    struct Splay {
        int cnt;
        int child[N][2], fa[N], key[N], size[N], h[N];
        char k[N];
        void dfs(int x)
        {
            if(child[x][0]) dfs(child[x][0]);
            printf("%c", k[x]);
            if(child[x][1]) dfs(child[x][1]);
        }
        inline bool wh(int x)
        {
            return child[fa[x]][1] == x;
        }
        inline void update(int x)
        {
            h[x] = (h[child[x][0]] * seed + key[x]) * pw[size[child[x][1]]] + h[child[x][1]];
            size[x] = size[child[x][0]] + size[child[x][1]] + 1;
        }
        inline void rotate(int x) 
        {
            int y = fa[x], z = fa[y], t = wh(x);        
            fa[x] = z;
            child[z][wh(y)] = x;
            child[y][t] = child[x][t ^ 1];
            fa[child[x][t ^ 1]] = y;
            child[x][t ^ 1] = y;
            fa[y] = x;
            update(y);
            update(x);
        }
        inline void splay(int x, int t)
        {
              if(fa[x] == t) return;
            for(int f; (f = fa[x]) != t; rotate(x)) 
                if(fa[f] != t) rotate((wh(x) == wh(f)) ? f : x);
            if(!t) root = x;
            update(root);
        }
        inline void build(int l, int r, int &x, char s[], int last)
        {
            if(l > r) return;
            int mid = (l + r) >> 1;
            key[x = ++cnt] = s[mid] - 'a';
            k[cnt] = s[mid];
            fa[x] = last;
            build(l, mid - 1, child[x][0], s, x);
            build(mid + 1, r, child[x][1], s, x);
            update(x);
        }
        inline void insert(int pos, char s[])
        {   
            int t, x = find(root, pos + 1), y = find(root, pos + 2);
            splay(x, 0);
            splay(y, root);        
            child[child[root][1]][0] = ++cnt;
            fa[cnt] = child[root][1];
            key[cnt] = s[0] - 'a';
            k[cnt] = s[0];
            update(cnt);
            update(child[root][1]);
            update(root);
        }
        inline int find(int x, int k)
        {
            if(size[child[x][0]] + 1 == k) return x;
            if(size[child[x][0]] >= k) return find(child[x][0], k);
            return find(child[x][1], k - size[child[x][0]] - 1);
        }
        inline void change(int pos, char s[])
        {
            int x = find(root, pos + 1);
            splay(x, 0);
            key[root] = s[0] - 'a';
            k[root] = s[0];
            update(root);
        }
        inline int Hash(int x, int y)
        {   
            x = find(root, x);
            y = find(root, y + 2);
            splay(x, 0);
            splay(y, root);          
            return h[child[y][0]];
        }
        inline bool check(int x, int y, int len)
        {
    //        if(x + len - 1 > cnt - 2 || y + len - 1 > cnt - 2) return false;
            return (Hash(x, x + len - 1) == Hash(y, y + len - 1));
        }
        inline void ask(int x, int y)
        {
            int l = -1, r = cnt - y, ans = 0;
             while(r - l > 1)
            {
                int mid = (l + r) >> 1;
                if(check(x, y, mid)) l = ans = mid;
                else r = mid;
            }
            printf("%d
    ", ans);
        }
    } splay;
    int main()
    {
    //    freopen("bzoj_1014.in", "r", stdin);
    //    freopen("bzoj_1014.out", "w", stdout);
        scanf("%s%d", s + 2, &m);
        n = strlen(s + 2);
        pw[0] = 1;
        for(int i = 1; i <= N - 10; ++i) pw[i] = pw[i - 1] * seed;
        s[1] = '?';
        ++n;
        s[++n] = '?';
        splay.build(1, n, root, s, 0);  
        while(m--)
        {
            char opt[10];
            int x, y;
            scanf("%s", opt);
            if(opt[0] == 'Q') 
            {
                scanf("%d%d", &x, &y);
                if(x > y) swap(x, y);
                splay.ask(x, y);
            }
            if(opt[0] == 'I')
            {
                scanf("%d%s", &x, s);
                splay.insert(x, s);
            }
            if(opt[0] == 'R')
            {
                scanf("%d%s", &x, s);
                splay.change(x, s);
            }
        }
    //    fclose(stdin);
    //     fclose(stdout);
        return 0;
    }    
    View Code
  • 相关阅读:
    idea中如何配置tomcat
    onselectstart属性解决双击出现的蓝色区域
    (二十二)数组的最大值和最小值
    (二十一)数组的初始化
    (二十)两种数据类型的对比
    (十九)数组的内存分配
    (十八)数组概述
    (十六)函数的重载
    (十七)自定义函数
    (十五)函数的入栈和出栈
  • 原文地址:https://www.cnblogs.com/19992147orz/p/7363120.html
Copyright © 2020-2023  润新知