[BZOJ3238][Ahoi2013]差异解题报告|后缀数组
Description
先分析一下题目,我们显然可以直接算出sigma(len[Ti]+len[Tj])的值=(n-1)*n*(n+1)/2
接着就要去算这个字符串中所有后缀的两两最长公共前缀总和
首先可以想到后缀数组,我们计算好后缀数组之后再进行对height数组的计算
对于以x,y开头的后缀,它们的最长公共前缀为min(height[sa[i]])(rank[x]<=i<=rank[y])
但从以往习惯的height数组入手我们发现并没有办法解决这个问题
不如换个角度思考,我们可以枚举这个最小的数!
我们定义一个区间内最小的height为数值最小的情况下下标最小的位置
那么一个数是最小的height,当且仅当这个区间的左边界到它的位置中没有数值小于等于它的数,它的右边界到它的位置中没有数值小于它的数
我们可以用单调栈处理处这个左边界和右边界最远可以到达的位置
然后乘法原理计算出答案就可以了
代码写得很长的样子...(不知道为什么别人的SA好像写得都比我短...
1 program bzoj3238; 2 const maxn=500010; 3 var s,a,rank,sa,tmp,height,l,r,st:array[-1..maxn]of int64; 4 ans,n:int64; 5 ss:ansistring; 6 i:longint; 7 8 function max(a,b:longint):longint; 9 begin 10 if a>b then exit(a) else exit(b); 11 end; 12 13 function compare(x,y,p:longint):longint; 14 begin 15 while (x+p-1<n)and(y+p-1<n)and(a[x+p-1]=a[y+p-1]) do inc(p); 16 exit(p-1); 17 end; 18 19 procedure Suffix_Array; 20 var i,j,p,size,v0,v1,v00,v01:longint; 21 begin 22 if n>26 then size:=n else size:=26; 23 for i:=0 to n-1 do rank[i]:=a[i]; 24 for i:=0 to size-1 do s[i]:=0; 25 for i:=0 to n-1 do inc(s[a[i]]); 26 for i:=1 to size-1 do inc(s[i],s[i-1]); 27 for i:=n-1 downto 0 do 28 begin 29 dec(s[a[i]]); 30 sa[s[a[i]]]:=i; 31 end; 32 j:=1; 33 while j<=n do 34 begin 35 p:=0; 36 for i:=n-j to n-1 do 37 begin 38 tmp[p]:=i;inc(p); 39 end; 40 for i:=0 to n-1 do if sa[i]-j>=0 then 41 begin 42 tmp[p]:=sa[i]-j;inc(p); 43 end; 44 for i:=0 to size-1 do s[i]:=0; 45 for i:=0 to n-1 do inc(s[rank[i]]); 46 for i:=1 to size-1 do inc(s[i],s[i-1]); 47 for i:=n-1 downto 0 do 48 begin 49 dec(s[rank[tmp[i]]]); 50 sa[s[rank[tmp[i]]]]:=tmp[i]; 51 end; 52 p:=0;tmp[sa[0]]:=0; 53 for i:=1 to n-1 do 54 begin 55 v0:=sa[i-1];v1:=sa[i]; 56 if v0+j<n then v00:=rank[v0+j] else v00:=-1; 57 if v1+j<n then v01:=rank[v1+j] else v01:=-1; 58 if (rank[v0]=rank[v1])and(v00=v01) then tmp[sa[i]]:=p else 59 begin 60 inc(p);tmp[sa[i]]:=p; 61 end; 62 end; 63 for i:=0 to n-1 do rank[i]:=tmp[i]; 64 j:=j << 1; 65 end; 66 end; 67 68 procedure Calc_Height; 69 var i:longint; 70 begin 71 if rank[0]=0 then height[0]:=0 else height[0]:=compare(0,sa[rank[0]-1],1); 72 for i:=1 to n-1 do 73 if rank[i]=0 then height[i]:=0 else height[i]:=compare(i,sa[rank[i]-1],max(height[i-1],1)); 74 end; 75 76 procedure Solve; 77 var i,top:longint; 78 begin 79 height[-1]:=-maxlongint; 80 st[0]:=-1;sa[-1]:=-1;top:=0; 81 for i:=0 to n-1 do 82 begin 83 while height[sa[st[top]]]>=height[sa[i]] do dec(top); 84 l[i]:=st[top]; 85 inc(top);st[top]:=i; 86 end; 87 st[0]:=n;sa[n]:=-1;top:=0; 88 for i:=n-1 downto 0 do 89 begin 90 while height[sa[st[top]]]>height[sa[i]] do dec(top); 91 r[i]:=st[top]; 92 inc(top);st[top]:=i; 93 end; 94 for i:=0 to n-1 do dec(ans,height[sa[i]]*(i-l[i])*(r[i]-i)*2); 95 writeln(ans); 96 end; 97 98 begin 99 readln(ss); 100 n:=length(ss); 101 for i:=1 to n do a[i-1]:=ord(ss[i])-96; 102 for i:=1 to n do inc(ans,i*(n-1)); 103 Suffix_Array; 104 Calc_Height; 105 Solve; 106 end.