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

 

posted @ 2018-09-07 12:55  Unstoppable728  阅读(206)  评论(0编辑  收藏  举报