BZOJ3238[Ahoi2013]差异

3238: [Ahoi2013]差异

Time Limit: 20 Sec  Memory Limit: 512 MB
Submit: 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;
}

 

posted @ 2017-07-08 21:58  QYP_2002  阅读(127)  评论(0编辑  收藏  举报