2018.11.24 spoj New Distinct Substrings(后缀数组)

版权声明:随意转载哦......但还是请注明出处吧: https://blog.csdn.net/dreaming__ldx/article/details/84441031

传送门
双倍经验(弱化版本)
考虑求出来 h e i g h t height 数组之后用增量法。
也就是考虑每增加一个 h e i g h t height 对答案产生的贡献。
算出来是 S h e i g h t i + 1 s a i \sum|S|-height_i+1-sa_i
代码:

#include<bits/stdc++.h>
#define ri register int
using namespace std;
const int N=5e4+5;
int n,m,rk[N],ht[N],sa[N],sa2[N];
char s[N];
inline void Sort(){
	static int cnt[N];
	for(ri i=1;i<=m;++i)cnt[i]=0;
	for(ri i=1;i<=n;++i)++cnt[rk[i]];
	for(ri i=2;i<=m;++i)cnt[i]+=cnt[i-1];
	for(ri i=n;i;--i)sa[cnt[rk[sa2[i]]]--]=sa2[i];
}
inline void getsa(){
	for(ri i=1;i<=n;++i)rk[i]=s[i]-'A'+1,sa2[i]=i;
	m=180,Sort();
	for(ri w=1,p=0;m!=n;w<<=1,p=0){
		for(ri i=n-w+1;i<=n;++i)sa2[++p]=i;
		for(ri i=1;i<=n;++i)if(sa[i]>w)sa2[++p]=sa[i]-w;
		Sort(),swap(sa2,rk),rk[sa[1]]=p=1;
		for(ri i=2;i<=n;++i)rk[sa[i]]=(sa2[sa[i]]==sa2[sa[i-1]]&&sa2[sa[i]+w]==sa2[sa[i-1]+w])?p:++p;
		m=p;
	}
	for(ri i=1,j,k=0;i<=n;ht[rk[i++]]=k)for(k?--k:k,j=sa[rk[i]-1];s[i+k]==s[j+k];++k);
}
int main(){
	ri tt;
	scanf("%d",&tt);
	for(ri ans=0;tt;--tt,cout<<ans<<'\n',ans=0){
		scanf("%s",s+1),n=strlen(s+1),getsa();
		for(ri i=1;i<=n;++i)ans+=n-sa[i]+1-ht[i];
	}
	return 0;
}

猜你喜欢

转载自blog.csdn.net/dreaming__ldx/article/details/84441031