题目
∑ i = 1 n ∑ j = i + 1 n l c p ( T i , T j ) \sum_{i=1}^n\sum_{j=i+1}^nlcp(T_i,T_j) i=1∑nj=i+1∑nlcp(Ti,Tj)
题解
即求
h
e
i
g
h
t
height
height数组所有的区间最小值
我竟然忘了单调栈怎么做。。。
又忘了s[i]-'a’后的+1…
调了一上午。。。
#include<bits/stdc++.h>
#define ll long long
using namespace std;
const int N=5e6+100;
int n,m;
char s[N];
int tp[N],sa[N],rk[N],t[N];
void Qsort()
{
for(int i=1;i<=m;i++)t[i]=0;
for(int i=1;i<=n;i++)t[rk[i]]++;
for(int i=1;i<=m;i++)t[i]+=t[i-1];
for(int i=n;i>=1;i--)sa[t[rk[tp[i]]]--]=tp[i];
}
void SA()
{
for(int i=1;i<=n;i++)rk[i]=s[i]-'a'+1,tp[i]=i;
Qsort();
for(int w=1,p=0;w<=n;m=p,w<<=1)
{
p=0;
for(int i=n-w+1;i<=n;i++)tp[++p]=i;
for(int i=1;i<=n;i++)if(sa[i]>w)tp[++p]=sa[i]-w;
Qsort();swap(tp,rk);p=rk[sa[1]]=1;
for(int i=2;i<=n;i++)rk[sa[i]]=(tp[sa[i]]==tp[sa[i-1]]&&tp[sa[i]+w]==tp[sa[i-1]+w])?p:++p;
if(p==n)return ;
}
}
int h[N];
void get_ht()
{
int k=0;
for(int i=1;i<=n;i++)
{
if(rk[i]==1)continue;
int j=sa[rk[i]-1];if(k)k--;
while(i+k<=n&&j+k<=n&&s[i+k]==s[j+k])k++;
h[rk[i]]=k;
}
}
int z[N],p;
int L[N],R[N];
signed main()
{
scanf("%s",s+1);
n=strlen(s+1);m=30;
SA();get_ht();
z[p=1]=1;
for(int i=2;i<=n;i++)
{
while(p&&h[z[p]]>h[i])R[z[p--]]=i;
L[i]=z[p];z[++p]=i;
}while(p)R[z[p--]]=n+1;
ll ans=(ll)n*(n-1)*(n+1)/2;
for(int i=2;i<=n;i++)
ans-=2ll*(R[i]-i)*(i-L[i])*h[i];
printf("%lld",ans);
}