分析:len(Ti)+len(Tj) 不难想,每个后缀出现了 n-1 次 ,所以总的长度是 n*(n+1)/2*(n-1),问题就转化成求:
我们知道对于 lcp(i,j)=min(ht[i+1...j]),则对于固定的 j ,lcp(i+1...j-1,j) 的值是非递增的,那么就可以用单调栈维护每个 ht[k] 的出现次数和后缀个数
代码:
#include<vector>
#include<cstdio>
#include<cstring>
#include<iostream>
using namespace std;
typedef long long LL;
const int N = 5E5+10;
char str[N];
int n,s[N],a[N],sa[N],rk[N],oldrk[N<<1];
int ht[N],px[N],id[N],cnt[N];
bool cmp(int x,int y,int w){
return oldrk[x]==oldrk[y] && oldrk[x+w]==oldrk[y+w];
}
void da(int s[],int n,int m){
int i,p=0,w,k;
for(i=1;i<=n;i++) ++cnt[rk[i] = s[i]];
for(i=1;i<=m;i++) cnt[i] += cnt[i-1];
for(i=n;i>=1;i--) sa[cnt[rk[i]]--] = i;
for(w=1;w<n;w<<=1,m=p){
for(p=0,i=n;i>n-w;i--) id[++p]=i;
for(i=1;i<=n;i++)
if(sa[i]>w) id[++p]=sa[i]-w;
memset(cnt,0,sizeof(cnt));
for(i=1;i<=n;i++) ++cnt[px[i] = rk[id[i]]];
for(i=1;i<=m;i++) cnt[i] += cnt[i-1];
for(i=n;i>=1;i--) sa[cnt[px[i]]--] = id[i];
memcpy(oldrk,rk,sizeof(rk));
for(p=0,i=1;i<=n;i++)
rk[sa[i]]=cmp(sa[i],sa[i-1],w)?p:++p;
}
for(i=1,k=0;i<=n;i++){
if(k) --k;
while(s[i+k]==s[sa[rk[i]-1]+k]) ++k;
ht[rk[i]]=k;
}
}
LL H[N][3],top=0;
LL ans=0;
int main()
{
scanf("%s",str+1);
n=strlen(str+1);
for(int i=1;i<=n;i++) s[i]=str[i];
da(s,n,128);
for(int i=2;i<=n;i++){
LL h=ht[i],num=n-i+1,tot=1;
while(top>0&&h<=H[top][0]){
ans+=H[top][0]*H[top][2]*tot;
LL num1=num+H[top][1]-H[top][2]*tot;
num=num1;
tot+=H[top][2];
--top;
}
if(h) H[++top][0]=h,H[top][1]=num,H[top][2]=tot;
}
for(int i=1;i<=top;i++) ans+=H[i][0]*H[i][1];
ans=(LL)n*(n+1)/2*(n-1)-ans*2;
printf("%lld",ans);
}