zoukankan      html  css  js  c++  java
  • bzoj1014: [JSOI2008]火星人prefix(splay+hash+二分)

      题目大意:一个字符串三个操作:①求两个后缀的LCP②插入一个字符③修改一个字符。

      前几天刚学了hash+二分求lcp,就看到这题。

      原来splay还能这么用?!原来splay模板这么好写?我以前写的splay是假的吧woc

      splay每个节点代表一个字符,并维护这个子树代表一个子串的哈希值。因为splay旋转不破坏树结构,所以不论怎么旋转这棵splay树都能代表这个字符串。

      预处理处理少了调了半天呜呜呜

      赶紧跑去更新自己的splay模板

    #include<iostream>
    #include<cstring>
    #include<cstdlib>
    #include<cstdio>
    #define which(x) (son[fa[x]][1]==x)
    #define ull unsigned long long
    using namespace std;
    const int maxn=500010;
    int n,m,x,y,tot,root;
    int fa[maxn],son[maxn][2],size[maxn],s[maxn];
    ull hs[maxn],mul[maxn];
    char st[maxn],ch[maxn],ch2[maxn];
    void read(int &k)
    {
        int f=1;k=0;char c=getchar();
        while(c<'0'||c>'9')c=='-'&&(f=-1),c=getchar();
        while(c<='9'&&c>='0')k=k*10+c-'0',c=getchar();
        k*=f;    
    }
    void update(int x)
    {
        size[x]=size[son[x][0]]+size[son[x][1]]+1;
        hs[x]=hs[son[x][0]]+mul[size[son[x][0]]]*s[x]+mul[size[son[x][0]]+1]*hs[son[x][1]];
    }
    void rotate(int x)
    {
        int f=fa[x];
        bool k=which(x);
        son[f][k]=son[x][!k];
        son[x][!k]=f;
        son[fa[f]][which(f)]=x;
        fa[son[f][k]]=f;
        fa[x]=fa[f];
        fa[f]=x;
        size[x]=size[f];
        hs[x]=hs[f];
        update(f);
    }
    void splay(int x,int g)
    {
        while(fa[x]!=g)
        {
            int f=fa[x];
            if(fa[f]==g)
            {
                rotate(x);
                break;
            }
            if(which(x)^which(f))rotate(x);
            else rotate(f);
            rotate(x);
        }
        if(!g)root=x;
    }
    int rank(int x,int k)
    {
        if(k<=size[son[x][0]])return rank(son[x][0],k);
        else if(k==(size[son[x][0]]+1))return x;
        else return rank(son[x][1],k-size[son[x][0]]-1);
    }
    int build(int l,int r,int f)
    {
        if(l>r)return 0;
        int x=++tot,mid=(l+r)>>1;
        fa[x]=f;s[x]=(int)(st[mid]-'a')+1;
        son[x][0]=build(l,mid-1,x);
        son[x][1]=build(mid+1,r,x);
        update(x);
        return x;
    }
    void insert(int k,int ch)
    {
        int x=rank(root,k),y=rank(root,k+1);
        splay(x,0);splay(y,x);
        s[++tot]=ch;
        fa[tot]=y;son[y][0]=tot;
        update(tot);update(y);update(x);
    }
    void change(int k,int ch)
    {
        int x=rank(root,k);
        splay(x,0);
        s[x]=ch;
        update(x);
    }
    int lcp(int kx,int ky)
    {
        int l=0,r=n;
        while(l<r)
        {
            int mid=(l+r+1)>>1;
            if(ky+mid>n+2)
            {
                r=mid-1;
                continue;
            }
            int x=rank(root,kx-1),y=rank(root,kx+mid);
            splay(x,0);splay(y,x);
            ull haxi=hs[son[y][0]];
            x=rank(root,ky-1),y=rank(root,ky+mid);
            splay(x,0);splay(y,x);
            if(haxi==hs[son[y][0]])l=mid;
            else r=mid-1;
        }
        return l;
    }
    int main()
    {
        scanf("%s",st+1);
        n=strlen(st+1);
        mul[0]=1;
        for(int i=1;i<=150010;i++)mul[i]=mul[i-1]*27;
        root=build(0,n+1,0);
        read(m);
        for(int i=1;i<=m;i++)
        {
            scanf("%s",ch);
            if(ch[0]=='Q')
            {
                read(x);read(y);
                if(x>y)swap(x,y);
                if(x!=y)printf("%d
    ",lcp(x+1,y+1));
                else printf("%d
    ",n-x+1);
            }
            if(ch[0]=='R')
            {
                read(x);
                scanf("%s",ch2);
                change(x+1,(int)(ch2[0]-'a')+1);
            }
            if(ch[0]=='I')
            {    
                read(x);
                scanf("%s",ch2);
                insert(x+1,(int)(ch2[0]-'a')+1);
                n++;
            }
        }
        return 0;
    }
    View Code
  • 相关阅读:
    php优秀框架codeigniter学习系列——安装,配置
    设计模式学习系列——桥接模式
    elasticsearch学习笔记——相关插件和使用场景
    elasticsearch学习笔记——安装,初步使用
    设计模式学习系列——适配器模式
    php优秀框架codeigniter学习系列——前言
    设计模式学习系列——原型模式
    angular 自定义指令 directive transclude 理解
    inq to datatable group by 多列 实现
    CSS3 media 入门
  • 原文地址:https://www.cnblogs.com/Sakits/p/7094773.html
Copyright © 2011-2022 走看看