CSU-1632 Repeated Substrings[后缀数组求重复出现的子串数目]
Posted 神犇(shenben)
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了CSU-1632 Repeated Substrings[后缀数组求重复出现的子串数目]相关的知识,希望对你有一定的参考价值。
评测地址:https://cn.vjudge.net/problem/CSU-1632
Description
求字符串中所有出现至少2次的子串个数
Input
第一行为一整数T(T<=10)表示用例组数,每组用例占一行为一个长度不超过100000的字符串
Output
对于每组用例,输出该串中所有出现至少两次的子串个数
Sample Input
3
aabaab
aaaaa
AaAaA
Sample Output
5
4
5
Solution
Ans=sum(max(height(i)-height(i-1),0))
#include<cstdio> #include<cstring> using namespace std; const int N=1e5+5; int T,n,ans,c[N],sa[N],tsa[N],trank[N],rank[N],h[N]; char s[N]; void DA(int maxx=256){ memset(c,0,sizeof c);int p; for(int i=1;i<=n;i++) c[rank[i]=s[i]]++; for(int i=2;i<=maxx;i++) c[i]+=c[i-1]; for(int i=n;i;i--) sa[c[rank[i]]--]=i; trank[sa[1]]=p=1; for(int i=2;i<=n;i++){ if(rank[sa[i]]!=rank[sa[i-1]]) p++; trank[sa[i]]=p; } for(int i=1;i<=n;i++) rank[i]=trank[i]; for(int k=1;p<n;k<<=1,maxx=p){ p=0; for(int i=n-k+1;i<=n;i++) tsa[++p]=i; for(int i=1;i<=n;i++) if(sa[i]>k) tsa[++p]=sa[i]-k; memset(c,0,sizeof c); for(int i=1;i<=n;i++) trank[i]=rank[tsa[i]]; for(int i=1;i<=n;i++) c[trank[i]]++; for(int i=2;i<=maxx;i++) c[i]+=c[i-1]; for(int i=n;i;i--) sa[c[trank[i]]--]=tsa[i]; trank[sa[1]]=p=1; for(int i=2;i<=n;i++){ if(rank[sa[i]]!=rank[sa[i-1]]||rank[sa[i]+k]!=rank[sa[i-1]+k]) p++; trank[sa[i]]=p; } for(int i=1;i<=n;i++) rank[i]=trank[i]; } for(int i=1,k=0;i<=n;i++){ int j=sa[rank[i]-1]; while(s[i+k]==s[j+k]) k++; h[rank[i]]=k;if(k>0)k--; } } void GO(){ ans=0; for(int i=1;i<=n;i++) if(h[i]>h[i-1]) ans+=h[i]-h[i-1]; printf("%d\n",ans); } int main(){ scanf("%d",&T); while(T--){ scanf("%s",s+1);n=strlen(s+1); DA(); GO(); } return 0; }
以上是关于CSU-1632 Repeated Substrings[后缀数组求重复出现的子串数目]的主要内容,如果未能解决你的问题,请参考以下文章