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\n", 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

 

posted @ 2017-08-15 08:44  19992147  阅读(160)  评论(0编辑  收藏  举报