暴力水过了。。
st表预处理出最小值点,每次寻找最小值点然后乘法原理计算两边的乘积。再对左右区间分别处理。6s妥妥水过。
卧槽我后缀数组居然写错了。。调了一早晨都以为是分治写错。。果然不能对自己的后缀数组太自信QAQ。
#include<bits/stdc++.h>
#define inf 1000000007
#define ll long long
#define N 500005
using namespace std;
char s[500005];
int len;
ll ans,sum;
int t1[N],t2[N],cc[N],sa[N],rank[N],height[N];
struct node {int v,id;} f[N][20];
inline bool cmp(int *y,int a,int b,int l)
{
int arank1=y[a];
int brank1=y[b];
int arank2=a+l>=len?-1:y[a+l];
int brank2=b+l>=len?-1:y[b+l];
return arank1==brank1&&arank2==brank2;
}
inline void make_sa()
{
int *x=t1,*y=t2;
int m=26;
for (int i=0;i<m;i++) cc[i]=0;
for (int i=0;i<len;i++) ++cc[x[i]=s[i]-'a'];
for (int i=1;i<m;i++) cc[i]+=cc[i-1];
for (int i=len-1;~i;i--) sa[--cc[x[i]]]=i;
for (int k=1;k<len;k<<=1)
{
int p=0;
for (int i=len-k;i<len;i++) y[p++]=i;
for (int i=0;i<len;i++)
if (sa[i]>=k) y[p++]=sa[i]-k;
for (int i=0;i<m;i++) cc[i]=0;
for (int i=0;i<len;i++) ++cc[x[y[i]]];
for (int i=1;i<m;i++) cc[i]+=cc[i-1];
for (int i=len-1;~i;i--) sa[--cc[x[y[i]]]]=y[i];
swap(x,y);
m=1; x[sa[0]]=0;
for (int i=1;i<len;i++)
x[sa[i]]=cmp(y,sa[i-1],sa[i],k)?m-1:m++;
if (m>=len) break;
}
}
inline void make_height()
{
for (int i=0;i<len;i++) rank[sa[i]]=i;
int k=0; height[0]=0;
for (int i=0;i<len;i++)
{
if (!rank[i]) continue;
int j=sa[rank[i]-1];
if (k) k--;
while (s[j+k]==s[i+k]) k++;
height[rank[i]]=k;
}
}
inline void make_st()
{
for (int i=1;i<len;i++) f[i][0]=(node){height[i],i}; f[0][0]=(node){inf,0};
for (int j=1;j<=19;j++)
for (int i=0;i<len;i++)
if (i+(1<<j)-1<len)
{
f[i][j]=f[i][j-1];
if (f[i][j].v>f[i+(1<<(j-1))][j-1].v)
f[i][j]=f[i+(1<<(j-1))][j-1];
}
}
inline node ask_min(int l,int r)
{
int k=log2(r-l+1);
if (f[l][k].v<f[r-(1<<k)+1][k].v) return f[l][k]; else return f[r-(1<<k)+1][k];
}
void dfs(int l,int r)
{
if (l>r) return;
if (l==r) {sum+=(ll)height[l]; return;}
node t=ask_min(l,r);
sum+=(ll)(t.id-l+1)*(r-t.id+1)*t.v;
dfs(l,t.id-1); dfs(t.id+1,r);
}
int main()
{
scanf("%s",s);
len=strlen(s);
ans=(ll)len*(len-1)*(len+1)/2;
make_sa();
make_height();
make_st();
dfs(1,len-1);
cout << ans-2*sum;
return 0;
}