都LCP了很显然是要用到后缀数组的
显然前面的那个东西是可以直接算出来的
关键在于LCP的和怎么快速的计算
不难想到穷举height[i],然后判断这个height[i]可能成为多少对后缀的LCP
考虑到LCP(i,j)=min(height[rank[i]+1~rank[j]]) 假定rank[i]<rank[j];
假设height[l]是左边第一个小于height[i]的,height[r]是右边第一个小于height[i]的
则height[i]是(i-l)(r-i)对后缀的LCP
但这样有一个问题,相同height可能会被重复计算
为了避免重复,我们定义height[r]是右边第一个不大于height[i]的
这样就有两种方法来实现
第一种是二分+rmq,但不幸的是我竟然写超时,而且我觉得容易出错
第二种是利用单调队列,我们把height[i]对应的l,r定义为左右边界,记为l[i],r[i];
计算左边界和右边界是相似的,这里我们讨论左边界
假如height[j]<=height[k] (j>k) 那么对于之后的height[i],
要么能延伸到k之前(height[i]<=height[j]),要么只能左边界就是j(height[i]>height[j]),不用比较height[k]
显然我们要维护一个单调不降的队列就行了
最后计算的时候注意用int64
1 var rank,sa,y,q,x,sum,h,l,r:array[0..600010] of longint; 2 s:ansistring; 3 i,n,m,p,j,t:longint; 4 ans,z:int64; 5 6 function min(a,b:longint):longint; 7 begin 8 if a>b then exit(b) else exit(a); 9 end; 10 11 procedure suffix; 12 var i,j,p:longint; 13 begin 14 for i:=1 to n do 15 begin 16 y[i]:=ord(s[i]); 17 inc(sum[y[i]]); 18 end; 19 m:=255; 20 for i:=1 to m do 21 inc(sum[i],sum[i-1]); 22 for i:=n downto 1 do 23 begin 24 sa[sum[y[i]]]:=i; 25 dec(sum[y[i]]); 26 end; 27 p:=1; 28 rank[sa[1]]:=1; 29 for i:=2 to n do 30 begin 31 if y[sa[i]]<>y[sa[i-1]] then inc(p); 32 rank[sa[i]]:=p; 33 end; 34 m:=p; 35 j:=1; 36 while m<n do 37 begin 38 fillchar(sum,sizeof(sum),0); 39 y:=rank; 40 p:=0; 41 for i:=n-j+1 to n do 42 begin 43 inc(p); 44 x[p]:=i; 45 end; 46 for i:=1 to n do 47 if sa[i]>j then 48 begin 49 inc(p); 50 x[p]:=sa[i]-j; 51 end; 52 53 for i:=1 to n do 54 begin 55 rank[i]:=y[x[i]]; 56 inc(sum[rank[i]]); 57 end; 58 for i:=1 to m do 59 inc(sum[i],sum[i-1]); 60 for i:=n downto 1 do 61 begin 62 sa[sum[rank[i]]]:=x[i]; 63 dec(sum[rank[i]]); 64 end; 65 p:=1; 66 rank[sa[1]]:=1; 67 for i:=2 to n do 68 begin 69 if (y[sa[i]]<>y[sa[i-1]]) or (y[sa[i]+j]<>y[sa[i-1]+j]) then inc(p); 70 rank[sa[i]]:=p; 71 end; 72 m:=p; 73 j:=j shl 1; 74 end; 75 h[1]:=0; 76 p:=0; 77 for i:=1 to n do 78 begin 79 if rank[i]=1 then continue; 80 j:=sa[rank[i]-1]; 81 while (i+p<=n) and (j+p<=n) and (s[i+p]=s[j+p]) do inc(p); 82 h[rank[i]]:=p; 83 if p>0 then dec(p); 84 end; 85 end; 86 87 function calc(i,x,y:int64):int64; 88 begin 89 exit(2*h[i]*(i-x)*(y-i)); 90 end; 91 92 begin 93 readln(s); 94 n:=length(s); 95 suffix; 96 z:=n; 97 ans:=(z+1)*z div 2*(z-1); 98 t:=0; 99 for i:=2 to n do 100 begin 101 while (t>0) and (h[q[t]]>=h[i]) do dec(t); 102 if t=0 then l[i]:=1 103 else l[i]:=q[t]; 104 inc(t); 105 q[t]:=i; 106 end; 107 t:=0; 108 for i:=n downto 2 do 109 begin 110 while (t>0) and (h[q[t]]>h[i]) do dec(t); //注意右边界是第一个不大于的height,防止重复 111 if t=0 then r[i]:=n+1 112 else r[i]:=q[t]; 113 inc(t); 114 q[t]:=i; 115 end; 116 for i:=2 to n do 117 ans:=ans-calc(i,l[i],r[i]); 118 writeln(ans); 119 end.