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
7
Q 1 7
Q 4 8
Q 10 11
R 3 a
Q 1 7
I 10 a
Q 2 11
Sample Output
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.