• bzoj1014 火星人prefix Splay 字符串Hash


    链接:http://www.lydsy.com/JudgeOnline/problem.php?id=1014

    题意:动态修改字符串,动态查询某两个后缀之间的$LCP$长度。

    这题肯定一堆人刚开始:$woc$这题好水啊,后缀数据结构放肆撸啊……

    等看到后半段:$woc$这个修改怎么改啊……

    实际上这个东西跟后缀数据结构半毛钱关系没有……正确做法就是$Hash$……不停地插入字符,修改整棵子树的$Hash$值,然后就是动态的修改$Hash$值……转啊转……修改……转……然后就出来了……

      1 #include<iostream>
      2 #include<cstdio>
      3 #include<algorithm>
      4 #include<cstring>
      5 #define ls(x) ((x)->ch[0])
      6 #define rs(x) ((x)->ch[1])
      7 #define fa(x) (x->pa)
      8 using namespace std;
      9 const int base=2333,maxn=100005;
     10 unsigned long long tim[maxn];char s[maxn];
     11 struct node
     12 {
     13     int size,num;unsigned long long Has;
     14     node *ch[2],*pa;
     15     node(int has);
     16     int islc(){return ls(pa)==this;}
     17     void maintain();
     18 }*null=new node(0),*root=null;
     19 node::node(int has)
     20 {
     21     ch[0]=ch[1]=pa=null;
     22     num=Has=has;size=has?1:0;
     23 }
     24 void node::maintain()
     25 {
     26     size=ch[0]->size+ch[1]->size+1;
     27     Has=ch[0]->Has*tim[ch[1]->size+1]+num*tim[ch[1]->size]+ch[1]->Has;
     28 }
     29 void Rotate(node* rt,int d)
     30 {
     31     node *t=rt->ch[d^1];
     32     if(rt->pa!=null)rt->pa->ch[rt->islc()^1]=t;else root=t;
     33     t->pa=rt->pa;
     34     rt->ch[d^1]=t->ch[d];
     35     if(t->ch[d]!=null)t->ch[d]->pa=rt;
     36     t->ch[d]=rt,rt->pa=t;
     37     rt->maintain();t->maintain();
     38 }
     39 void Splay(node* x,node *tar)
     40 {
     41     for(node *rt=x->pa;rt!=tar;rt=x->pa)
     42     {
     43         if(rt->pa==tar){Rotate(rt,x->islc());break;}
     44         if(x->islc()==rt->islc())Rotate(rt->pa,x->islc());
     45         else Rotate(rt,x->islc());
     46         Rotate(x->pa,x->islc());
     47     }
     48     x->maintain();
     49 }
     50 void find(node *rt,int val,node *tar)
     51 {
     52     for(;;)
     53     {
     54         if(val<=ls(rt)->size)rt=ls(rt);
     55         else
     56         {
     57             val-=ls(rt)->size;
     58             if(val==1)break;
     59             val--,rt=rs(rt);
     60         }
     61     }
     62     Splay(rt,tar);
     63 }
     64 void build(node* &x,int l,int r)
     65 {
     66     if(l>r)return ;
     67     int mid=(l+r)>>1;x=new node(s[mid]-'a'+1);
     68     build(x->ch[0],l,mid-1),build(x->ch[1],mid+1,r);
     69     x->ch[0]->pa=x,x->ch[1]->pa=x;x->maintain();
     70 }
     71 void init()
     72 {
     73     tim[0]=1;
     74     for(int i=1;i<=100001;i++)tim[i]=tim[i-1]*base;
     75     scanf("%s",s);root=new node(20010117),root->ch[1]=new node(20010117);
     76     build(root->ch[1]->ch[0],0,strlen(s)-1);
     77     root->ch[1]->ch[0]->pa=root->ch[1],root->ch[1]->pa=root;root->ch[1]->maintain(),root->maintain();
     78 }
     79 bool check(int x,int y,int val)
     80 {
     81     find(root,x,null);find(root,x+val+1,root);
     82     unsigned long long Has1=root->ch[1]->ch[0]->Has;
     83     find(root,y,null);find(root,y+val+1,root);
     84     unsigned long long Has2=root->ch[1]->ch[0]->Has;
     85     return Has1==Has2;
     86 }
     87 int Query(int x,int y)
     88 {
     89     int l=0,r=root->size-1-max(x,y),mid;
     90     while(l<=r)
     91     {
     92         mid=(l+r)>>1;
     93         if(check(x,y,mid))l=mid+1;
     94         else r=mid-1;
     95     }
     96     return r;
     97 }
     98 int haha()
     99 {
    100     init();char s[5];
    101     int m;scanf("%d",&m);
    102     while(m--)
    103     {
    104         scanf("%s",s);int x,y;
    105         switch(s[0])
    106         {
    107             case 'R':scanf("%d%s",&x,s);
    108                     find(root,x+1,null);
    109                     root->num=s[0]-'a'+1;root->maintain();break;
    110             case 'I':scanf("%d%s",&x,s);
    111                     find(root,x+1,null);find(root,x+2,root);
    112                     root->ch[1]->ch[0]=new node(s[0]-'a'+1),root->ch[1]->ch[0]->pa=root->ch[1];root->ch[1]->maintain();root->maintain();break;
    113             default:scanf("%d%d",&x,&y);printf("%d
    ",Query(x,y));
    114         }
    115     }
    116 }
    117 int sb=haha();
    118 int main(){;}
    bzoj1014
  • 相关阅读:
    关于codeblocks插件(持续更新)
    自定义gvim配色方案qiucz.vim的源码
    mark it
    poj 1032
    poj 1028
    最小公倍数是lcm
    problems
    hdu 1067
    某些题的做法。。。
    突然明白了什么
  • 原文地址:https://www.cnblogs.com/Loser-of-Life/p/7588748.html
Copyright © 2020-2023  润新知