BZOJ3238[Ahoi2013]差异
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; }