3238: [Ahoi2013]差异
Time Limit: 20 Sec Memory Limit: 512 MBSubmit: 3266 Solved: 1483
[Submit][Status][Discuss]
Description

Input
一行,一个字符串S
Output
一行,一个整数,表示所求值
Sample Input
cacao
Sample Output
54
HINT
2<=N<=500000,S由小写英文字母组成
思路{后缀数组套路题,不解释,去看品酒大会吧。。。。}
#include <algorithm>
#include <iostream>
#include <cstring>
#include <cstdlib>
#include <cstdio>
#include <vector>
#include <cmath>
#include <queue>
#include <stack>
#include <map>
#include <set>
#define inf (1<<30)
#define il inline
#define RG register
#define LL long long
#define maxx 500010
using namespace std;
char r[maxx];LL tong[maxx],X[maxx],Y[maxx],rnk[maxx],sa[maxx],height[maxx],sz[maxx],fa[maxx];LL ans[maxx],Ans;
il bool comp(LL *s,LL a,LL b,LL len){return s[a]==s[b]&&s[a+len]==s[b+len];}
il void build_sa(int n){
LL *x=X,*y=Y,*t,Max=99999;
for(RG LL i=0;i<n;++i)tong[x[i]=r[i]]++;
for(RG LL i=1;i<=Max;++i)tong[i]+=tong[i-1];
for(RG LL i=n-1;i!=-1;i--)sa[--tong[x[i]]]=i;
for(RG LL j=1,i,p=0;p<n;j<<=1,Max=p){
for(i=n-1,p=0;i>=n-j;--i)y[p++]=i;
for(i=0;i<n;++i)if(sa[i]>=j)y[p++]=sa[i]-j;
memset(tong,0,sizeof(tong));
for(i=0;i<n;++i)tong[x[y[i]]]++;
for(i=1;i<=Max;++i)tong[i]+=tong[i-1];
for(i=n-1;i!=-1;i--)sa[--tong[x[y[i]]]]=y[i];
for(t=x,x=y,y=t,i=1,p=1,x[sa[0]]=0;i<n;++i)
x[sa[i]]=comp(y,sa[i],sa[i-1],j)?p-1:p++;
}
}
int n;
void geth(){
RG LL i,j,k=0;
for(i=1;i<=n;++i)rnk[sa[i]]=i;
for(i=0;i<n;height[rnk[i++]]=k)
for(k?k--:0,j=sa[rnk[i]-1];r[i+k]==r[j+k];k++);
}
struct segment{
LL l,r,len;
segment() {}
segment(LL _l,LL _r,LL L):l(_l),r(_r),len(L) {}
}w[maxx];
il bool Comp(const segment & a,const segment & b){return a.len>b.len;}
il LL find(LL x){if(fa[x]!=x)fa[x]=find(fa[x]);return fa[x];}
void Insert(LL x,LL y,LL H){
fa[x]=y;ans[H]+=sz[x]*sz[y];
sz[y]+=sz[x];
}
il void work(){
scanf("%s",r);n=strlen(r);r[n]=0;build_sa(n+1),geth();
for(RG LL i=2;i<=n;++i)w[i-1]=segment(sa[i],sa[i-1],height[i]);
sort(w+1,w+n,Comp);for(RG int i=0;i<n;++i)fa[i]=i,sz[i]=1;
for(RG LL i=1;i<n;++i)Ans+=((n-i+1)*(n-i)/2)+(n-i+1)*(n-i);
for(RG LL i=1;i<n;++i){
LL x=find(w[i].l),y=find(w[i].r);
if(x!=y)Insert(x,y,w[i].len);
}for(RG LL i=n;i>=1;i--)Ans-=2*ans[i]*i;
printf("%lld",Ans);return;
}
int main(){
freopen("1.in","r",stdin);
// freopen("1.out","w",stdout);
work();return 0;
}