题目大意:求 ∑1≤i<j≤nlen(Suffixi)+len(Suffixj)−2∗LCP(Suffixi,Suffixj) ∑ 1 ≤ i < j ≤ n l e n ( S u f f i x i ) + l e n ( S u f f i x j ) − 2 ∗ L C P ( S u f f i x i , S u f f i x j )
len(Suffixi)+len(Suffixj)
l
e
n
(
S
u
f
f
i
x
i
)
+
l
e
n
(
S
u
f
f
i
x
j
)
可以被提出来
剩下的就是要求
∑1≤i<j≤nLCP(Suffixi,Suffixj)
∑
1
≤
i
<
j
≤
n
L
C
P
(
S
u
f
f
i
x
i
,
S
u
f
f
i
x
j
)
因为
LCP(Suffixi,Suffixj)
L
C
P
(
S
u
f
f
i
x
i
,
S
u
f
f
i
x
j
)
等价于
Min{Heighti...j}
M
i
n
{
H
e
i
g
h
t
i
.
.
.
j
}
单调栈维护即可
代码如下:
#include<algorithm>
#include<cstring>
#include<cstdio>
#define N 500050
using namespace std;
char str[N];
long long ans;
int n,m,top;
int SA[N],las[N],rk[N],buck[N],height[N],l[N],r[N];
inline bool judge(int x,int y,int k){
return las[x]==las[y] && las[x+k]==las[y+k];
}
inline void Radix_Sort(){
for(int i=1;i<=m;i++) buck[i]=0;
for(int i=1;i<=n;i++) buck[rk[las[i]]]++;
for(int i=1;i<=m;i++) buck[i]+=buck[i-1];
for(int i=n;i>=1;i--) SA[buck[rk[las[i]]]--]=las[i];
}
inline void Get_SA(){
n=strlen(str+1);
for(int i=1;i<=n;i++){
las[i]=i;rk[i]=str[i];
}
m=127;Radix_Sort();m=0;
for(int i=1;m<n;i<<=1,top=0){
for(int j=n-i+1;j<=n;j++) las[++top]=j;
for(int j=1;j<=n;j++) if(SA[j]>i) las[++top]=SA[j]-i;
Radix_Sort();m=0;
for(int j=1;j<=n;j++) las[j]=rk[j];
for(int j=1;j<=n;j++) rk[SA[j]]=judge(SA[j],SA[j-1],i)?m:++m;
}
for(int i=1,j=0;i<=n;i++,j=max(j-1,0)){
while(str[i+j]==str[SA[rk[i]-1]+j]) j++;
height[rk[i]]=j;
}
}
struct sta{
int x,id;
}s[N];
int main(){
scanf("%s",str+1);
Get_SA();
top=0;
for(int i=1;i<=n;i++){
while(top && height[i]<s[top].x)
r[s[top--].id]=i;
s[++top].x=height[i];
s[top].id=i;
}
while(top) r[s[top--].id]=n+1;
for(int i=n;i;i--){
while(top && height[i]<=s[top].x)
l[s[top--].id]=i;
s[++top].x=height[i];
s[top].id=i;
}
while(top) r[s[top--].id]=0;
ans=1ll*(n+1)*n*(n-1)/2;
for(int i=1;i<=n;i++) ans=ans-2ll*height[i]*(i-l[i])*(r[i]-i);
printf("%lld",ans);
return 0;
}