BZOJ1014:[JSOI2008]火星人prefix

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

HINT

1、所有字符串自始至终都只有小写字母构成。
2、M<=150,000
3、字符串长度L自始至终都满足L<=100,000
4、询问操作的个数不超过10,000个。
对于第1,2个数据,字符串长度自始至终都不超过1,000
对于第3,4,5个数据,没有插入操作。

 

题解:

SPLAY!

维护字符串HASH值,二分答案并验证。

 

代码:

(写的常数有点大,并没有AC。)

  1 var
  2   v,h,p:array[-1..150005]of int64;
  3   size,fa:array[-1..150005]of longint;
  4   c:array[-1..150005,1..2]of longint;
  5   chh:array[1..150005,0..1]of char;
  6   pp:array[1..150005,1..2]of longint;
  7   i,j,k,l,kk,n,m,root:longint;
  8   ch,ch2:char;
  9   s:ansistring;
 10 function min(a,b:longint):longint;
 11 begin
 12   if a>b then exit(b);
 13   exit(a);
 14 end;
 15 procedure up(x:longint);
 16 begin
 17   h[x]:=(h[c[x,1]])and 1073741823;
 18   h[x]:=(h[x]+p[size[c[x,1]]]*v[x])and 1073741823;
 19   h[x]:=(h[x]+h[c[x,2]]*p[size[c[x,1]]+1])and 1073741823;
 20   size[x]:=size[c[x,1]]+1+size[c[x,2]];
 21 end;
 22 function find(x,y:longint):longint;
 23 begin
 24   while true do
 25   begin
 26     if size[c[x,1]]>=y then x:=c[x,1] else
 27     if size[c[x,1]]+1=y then exit(x) else
 28     begin y:=y-size[c[x,1]]-1; x:=c[x,2]; end;
 29   end;
 30 end;
 31 procedure left(x:longint;var xx:longint);
 32 var k,y:longint;
 33 begin
 34   y:=fa[x];
 35   k:=c[x,2]; c[x,2]:=y; fa[k]:=y; c[y,1]:=k;
 36   if y<>xx then
 37   begin if c[fa[y],1]=y then c[fa[y],1]:=x else c[fa[y],2]:=x; end;
 38   fa[x]:=fa[y]; fa[y]:=x;
 39   if y=xx then xx:=x;
 40   up(y); up(x);
 41 end;
 42 procedure right(x:longint;var xx:longint);
 43 var k,y:longint;
 44 begin
 45   y:=fa[x];
 46   k:=c[x,1]; c[x,1]:=y; fa[k]:=y; c[y,2]:=k;
 47   if y<>xx then
 48   begin if c[fa[y],1]=y then c[fa[y],1]:=x else c[fa[y],2]:=x; end;
 49   fa[x]:=fa[y]; fa[y]:=x;
 50   if y=xx then xx:=x;
 51   up(y); up(x);
 52 end;
 53 procedure splay(x:longint;var xx:longint);
 54 var y,z:longint;
 55 begin
 56   while x<>xx do
 57   begin
 58     y:=fa[x]; z:=fa[y];
 59     if y=xx then
 60     begin if c[y,1]=x then left(x,xx)else right(x,xx); end
 61     else if c[y,1]=x then
 62     begin
 63       if c[z,1]=y then left(y,xx)else left(x,xx);
 64     end else
 65     begin
 66       if c[z,1]=y then right(x,xx)else right(y,xx);
 67     end;
 68   end;
 69 end;
 70 function qq(k,l:longint):longint;
 71 var x,y:longint;
 72 begin
 73   x:=find(root,k); y:=find(root,k+l+1);
 74   splay(x,root); splay(y,c[x,2]);
 75   exit(h[c[y,1]]);
 76 end;
 77 function solve(x,y:longint):longint;
 78 var l,r,mid,i:longint;
 79 begin
 80   l:=find(root,x+1); r:=find(root,y+1);
 81   if v[l]<>v[r] then exit(0);
 82   l:=1; r:=min(n-x,n-y);
 83   while l+1<r do
 84   begin
 85     mid:=(l+r)div 2;
 86     if qq(x,mid)=qq(y,mid) then l:=mid else r:=mid-1;
 87   end;
 88   if qq(x,r)=qq(y,r)then exit(r)else exit(l);
 89 end;
 90 procedure bulid(l,r,f:longint);
 91 var mid:longint;
 92 begin
 93   if l>r then exit;
 94   if l=r then
 95   begin
 96     if l=0 then v[l]:=0 else v[l]:=ord(s[l])-ord('a')+1;
 97     h[l]:=v[l]; fa[l]:=f; size[l]:=1;
 98     if l<f then c[f,1]:=l else c[f,2]:=l;
 99     exit;
100   end;
101   mid:=(l+r)div 2;
102   bulid(l,mid-1,mid); bulid(mid+1,r,mid);
103   if mid=0 then v[mid]:=0 else
104   v[mid]:=ord(s[mid])-ord('a')+1; fa[mid]:=f; up(mid);
105   if mid<f then c[f,1]:=mid else c[f,2]:=mid;
106 end;
107 begin
108   p[0]:=1; for i:=1 to 150004 do p[i]:=(p[i-1]*27)and 1073741823;
109   for i:=-1 to 150004 do begin c[i,1]:=-1; c[i,2]:=-1; end;
110   readln(s); s:=s+chr(ord('a')-1); n:=length(s);
111   bulid(0,n,-1); root:=n div 2;
112   readln(m);
113   for i:=1 to m do
114   begin
115     read(ch); read(ch2); chh[i,0]:=ch;
116     case ch of
117       'Q':readln(pp[i,1],pp[i,2]);
118       'R':begin read(pp[i,1],ch); readln(chh[i,1]); end;
119       'I':begin read(pp[i,1],ch); readln(chh[i,1]); end;
120     end;
121   end;
122   while(m>0)and(chh[m,0]<>'Q')do dec(m);
123   for i:=1 to m do
124   begin
125     case chh[i,0] of
126       'Q':begin writeln(solve(pp[i,1],pp[i,2])); end;
127       'R':begin
128         l:=find(root,pp[i,1]+1); splay(l,root);
129         v[l]:=ord(chh[i,1])-ord('a')+1; up(l);
130       end;
131       'I':begin
132         l:=find(root,pp[i,1]+1); splay(l,root);
133         l:=find(root,pp[i,1]+2); splay(l,c[root,2]);
134         inc(n); c[l,1]:=n; fa[n]:=l;
135         v[n]:=ord(chh[i,1])-ord('a')+1; c[n,1]:=-1; c[n,2]:=-1;
136         up(n); up(fa[n]); up(root);
137       end;
138     end;
139   end;
140 end.
View Code
posted @ 2017-01-17 21:09  GhoStreach  阅读(149)  评论(0编辑  收藏  举报