2018.11.24 spoj New Distinct Substrings(后缀数组)

传送门

双倍经验(弱化版本)

考虑求出来heightheightheight数组之后用增量法。

也就是考虑每增加一个heightheightheight对答案产生的贡献。

算出来是∑∣S∣−heighti+1−sai\sum|S|-height_i+1-sa_i∑∣S∣−heighti​+1−sai​

代码:

#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;
}
上一篇:2018.11.24 poj3415Common Substrings(后缀数组+单调栈)


下一篇:sharding sphere 分多张表不支持 xml 中的批量更新以及解决方式