BZOJ 3238: [Ahoi2013]差异【后缀数组+单调栈】

版权声明:本文为博主原创文章,未经博主允许必须转载。 https://blog.csdn.net/C20181220_xiang_m_y/article/details/88955617

题面:

在这里插入图片描述

题目分析:

前面的 l e n T i + l e n T j = n ( n + 1 ) / 2 ( n 1 ) \sum lenTi+lenTj = n*(n+1)/2 * (n-1)
考虑后面怎么求。
只需要把后缀数组中的height值拿来乱搞。

两个排名分别为i,j的后缀,它们的LCP就是height[i+1,j]的最小值。

枚举排名从小到大,维护一个height值递增的栈,把栈中的贡献存在ret中,每次比较栈顶和当前height值的大小,如果比当前值小就ret-=它的那段贡献(对应的长度*height值)然后弹出,最后ret+=当前的height对应的区间长度*height值,然后ans-=ret*2。
搞一个结构体存长度和height值就好了。

Code:

#include<cstdio>
#include<cstring>
#include<algorithm>
#define maxn 500005
using namespace std;
int ary[4][maxn],b[maxn],height[maxn];
int *sa=ary[0],*rk=ary[1],*nsa=ary[2],*nrk=ary[3];
void cal_sa(int n,int m,int *a){
	for(int i=1;i<=n;i++) b[a[i]]++;
	for(int i=1;i<=m;i++) b[i]+=b[i-1];
	for(int i=1;i<=n;i++) sa[b[a[i]]--]=i;
	for(int i=1;i<=n;i++) rk[sa[i]]=rk[sa[i-1]]+(a[sa[i-1]]!=a[sa[i]]);
	for(int k=1;k<n&&rk[sa[n]]<n;k<<=1){
		for(int i=1;i<=n;i++) b[rk[sa[i]]]=i;
		for(int i=n;i>=1;i--) if(sa[i]>k) nsa[b[rk[sa[i]-k]]--]=sa[i]-k;
		for(int i=n-k+1;i<=n;i++) nsa[b[rk[i]]--]=i;
		for(int i=1;i<=n;i++) nrk[nsa[i]]=nrk[nsa[i-1]]+(rk[nsa[i-1]]!=rk[nsa[i]]||rk[nsa[i-1]+k]!=rk[nsa[i]+k]);
		swap(sa,nsa),swap(rk,nrk);
	}
}
void cal_height(int n,int *a){
	for(int i=1,k=0;i<=n;i++) if(rk[i]!=1){
		if(k) k--;
		for(int j=sa[rk[i]-1];a[j+k]==a[i+k];k++);
		height[rk[i]]=k;
	}
}
int n,a[maxn],top;
long long ans,ret;
char s[maxn];
struct node{
	int x,len;
	node(){}
	node(int x,int len):x(x),len(len){}
}q[maxn];
int main()
{
	scanf("%s",s+1),n=strlen(s+1);
	for(int i=1;i<=n;i++) a[i]=s[i]-'a'+1;
	cal_sa(n,26,a),cal_height(n,a);
	for(int i=2;i<=n;i++){
		int len=1;
		while(top&&q[top].x>=height[i]) len+=q[top].len,ret-=1ll*q[top].len*q[top].x,top--;
		ret+=1ll*len*height[i];
		ans+=ret;
		q[++top]=node(height[i],len);
	}
	printf("%lld\n",1ll*n*(n+1)/2*(n-1)-2*ans);
}

PS:我的cal_height函数没有判断i+k<=n,所以必须保证串的末尾的后面那个元素不等于串中的元素。所以转换的时候是a[i]=s[i]-‘a’+1而不能是a[i]=s[i]-‘a’

Upd:对于将串反转之后用后缀自动机构建后缀树的解法可以看这里(这篇blog里面似乎没有将串反转。。数据太水??)

猜你喜欢

转载自blog.csdn.net/C20181220_xiang_m_y/article/details/88955617
今日推荐