zoukankan      html  css  js  c++  java
  • BZOJ1014[JSOI2008]火星人prefix(splay维护hash)

    Description

      火星人最近研究了一种操作:求一个字串两个后缀的公共前缀。比方说,有这样一个字符串:madamimadam,
    我们将这个字符串的各个字符予以标号:序号: 1 2 3 4 5 6 7 8 9 10 11 字符 m a d a m i m a d a m 现在,
    火星人定义了一个函数LCQ(x, y),表示:该字符串中第x个字符开始的字串,与该字符串中第y个字符开始的字串
    ,两个字串的公共前缀的长度。比方说,LCQ(1, 7) = 5, LCQ(2, 10) = 1, LCQ(4, 7) = 0 在研究LCQ函数的过程
    中,火星人发现了这样的一个关联:如果把该字符串的所有后缀排好序,就可以很快地求出LCQ函数的值;同样,
    如果求出了LCQ函数的值,也可以很快地将该字符串的后缀排好序。 尽管火星人聪明地找到了求取LCQ函数的快速
    算法,但不甘心认输的地球人又给火星人出了个难题:在求取LCQ函数的同时,还可以改变字符串本身。具体地说
    ,可以更改字符串中某一个字符的值,也可以在字符串中的某一个位置插入一个字符。地球人想考验一下,在如此
    复杂的问题中,火星人是否还能够做到很快地求取LCQ函数的值。

    Input

      第一行给出初始的字符串。第二行是一个非负整数M,表示操作的个数。接下来的M行,每行描述一个操作。操
    作有3种,如下所示
    1、询问。语法:Qxy,x,y均为正整数。功能:计算LCQ(x,y)限制:1<=x,y<=当前字符串长度。
    2、修改。语法:Rxd,x是正整数,d是字符。功能:将字符串中第x个数修改为字符d。限制:x不超过当前字
    符串长度。
    3、插入:语法:Ixd,x是非负整数,d是字符。功能:在字符串第x个字符之后插入字符d,如果x=0,则在字
    符串开头插入。限制:x不超过当前字符串长度

    Output

      对于输入文件中每一个询问操作,你都应该输出对应的答案。一个答案一行。

    Sample Input

    madamimadam
    7
    Q 1 7
    Q 4 8
    Q 10 11
    R 3 a
    Q 1 7
    I 10 a
    Q 2 11

    Sample Output

    5
    1
    0
    2
    1

    解题思路:

    假如给你一个不变的序列,求最长公共前缀可以二分check()

    splay维护hash

    hash的本质就是前面的部分*后面的长度+后面的部分。

    splay维护一下子树hash值就好了。

    代码:

      1 #include<cstdio>
      2 #include<cstring>
      3 #include<algorithm>
      4 #define lll tr[spc].ch[0]
      5 #define rrr tr[spc].ch[1]
      6 #define ls ch[0]
      7 #define rs ch[1]
      8 typedef unsigned long long lnt;
      9 const int N=200000;
     10 const lnt M=9827601ull;
     11 struct trnt{
     12     int ch[2];
     13     int fa;
     14     int wgt;
     15     lnt val;
     16     lnt hax;
     17 }tr[N];
     18 int n,m;
     19 int root;
     20 int siz;
     21 lnt mal[N];
     22 char lne[N];
     23 char cmd[10];
     24 lnt a[N];
     25 bool whc(int spc)
     26 {
     27     return tr[tr[spc].fa].rs==spc;
     28 }
     29 void pushup(int spc)
     30 {
     31     tr[spc].wgt=tr[lll].wgt+tr[rrr].wgt+1;
     32     tr[spc].hax=tr[lll].hax*mal[tr[rrr].wgt+1]+tr[spc].val*mal[tr[rrr].wgt]+tr[rrr].hax;
     33     return ;
     34 }
     35 int place(int spc,int rnk)
     36 {
     37     if(tr[lll].wgt>=rnk)
     38         return place(lll,rnk);
     39     if(tr[lll].wgt+1==rnk)
     40         return spc;
     41     return place(rrr,rnk-tr[lll].wgt-1);
     42 }
     43 void rotate(int spc)
     44 {
     45     int f=tr[spc].fa;
     46     bool k=whc(spc);
     47     tr[f].ch[k]=tr[spc].ch[!k];
     48     tr[spc].ch[!k]=f;
     49     tr[tr[f].fa].ch[whc(f)]=spc;
     50     tr[spc].fa=tr[f].fa;
     51     tr[f].fa=spc;
     52     tr[tr[f].ch[k]].fa=f;
     53     pushup(f);
     54     pushup(spc);
     55     return ;
     56 }
     57 void splay(int spc,int f)
     58 {
     59     while(tr[spc].fa!=f)
     60     {
     61         int ft=tr[spc].fa;
     62         if(tr[ft].fa==f)
     63         {
     64             rotate(spc);
     65             break;
     66         }
     67         if(whc(spc)^whc(ft))
     68             rotate(spc);
     69         else
     70             rotate(ft);
     71         rotate(spc);
     72     }
     73     if(!f)
     74         root=spc;
     75 }
     76 void build(int l,int r,int &spc,int f)
     77 {
     78     if(l>r)
     79         return ;
     80     spc=++siz;
     81     int mid=(l+r)>>1;
     82     tr[spc].fa=f;
     83     tr[spc].val=a[mid];
     84     build(l,mid-1,lll,spc);
     85     build(mid+1,r,rrr,spc);
     86     pushup(spc);
     87     return ;
     88 }
     89 bool LCQ(int la,int lb,int len)
     90 {
     91     if(la+len-1>n||lb+len-1>n)
     92         return false;
     93     splay(place(root,la),0);
     94     splay(place(root,la+len+1),root);
     95     int spc=tr[tr[root].rs].ls;
     96     lnt a1=tr[spc].hax;
     97     splay(place(root,lb),0);
     98     splay(place(root,lb+len+1),root);
     99     spc=tr[tr[root].rs].ls;
    100     if(tr[spc].hax==a1)
    101         return true;
    102     return false;
    103 }
    104 int main()
    105 {
    106     scanf("%s",lne+1);
    107     n=strlen(lne+1);
    108     mal[0]=1;
    109     for(int i=1;i<N;i++)
    110     {
    111         mal[i]=mal[i-1]*M;
    112         a[i]=lne[i];
    113     }
    114     scanf("%d",&m);
    115     build(0,n+1,root,0);
    116     while(m--)
    117     {
    118         scanf("%s",cmd);
    119         if(cmd[0]=='Q')
    120         {
    121             int sa,sb;
    122             scanf("%d%d",&sa,&sb);
    123             int ans=0;
    124             int l,r;
    125             l=1;r=siz-2;
    126             while(l<=r)
    127             {
    128                 int mid=(l+r)>>1;
    129                 if(LCQ(sa,sb,mid))
    130                 {
    131                     l=mid+1;
    132                     ans=mid;
    133                 }else
    134                     r=mid-1;
    135             }
    136             printf("%d
    ",ans);
    137         }else if(cmd[0]=='R')
    138         {
    139             int pos;
    140             scanf("%d",&pos);
    141             scanf("%s",cmd);
    142             splay(place(root,pos+1),0);
    143             tr[root].val=cmd[0];
    144             pushup(root);
    145         }else if(cmd[0]=='I')
    146         {
    147             siz++;
    148             n++;
    149             int pos;
    150             scanf("%d",&pos);
    151             scanf("%s",cmd);
    152             splay(place(root,pos+1),0);
    153             splay(place(root,pos+2),root);
    154             int spc=tr[root].rs;
    155             tr[siz].val=cmd[0];
    156             tr[siz].fa=spc;
    157             tr[spc].ls=siz;
    158             pushup(siz);
    159             pushup(spc);
    160             pushup(root);
    161         }
    162     }
    163     return 0;
    164 }
  • 相关阅读:
    window 操作
    idea使用
    安装zookeeper
    resource和autowired
    python浅见 (Python 3000)
    Tomcat服务器
    servlet
    事件是一种委托吗?什么是委托?什么是事件?
    int值类型的ToString()方法是否装箱
    抽象类,虚方法与普通类的区别
  • 原文地址:https://www.cnblogs.com/blog-Dr-J/p/9602024.html
Copyright © 2011-2022 走看看