http://www.spoj.com/problems/SUBST1/
SUBST1 - New Distinct Substrings
Given a string, we need to find the total number of its distinct substrings.
Input
T- number of test cases. T<=20; Each test case consists of one string, whose length is <= 50000
Output
For each test case output one number saying the number of distinct substrings.
Example
Input: 2 CCCCC ABABA Output: 5 9
代码:
//论文题,每个子串都是某个后缀的前缀,因此每个后缀的贡献是len-sa[i],去掉重复的就是len-sa[i]-he[i]; #include<iostream> #include<cstdio> #include<cstring> using namespace std; const int MAXN=50000; int he[MAXN+9],ra[MAXN+9],sa[MAXN+9],xx[MAXN+9],yy[MAXN+9],buc[MAXN+9]; char s[MAXN+9]; int len,m; void get_suf() { int *x=xx,*y=yy; for(int i=0;i<m;i++) buc[i]=0; for(int i=0;i<len;i++) buc[x[i]=s[i]]++; for(int i=1;i<m;i++) buc[i]+=buc[i-1]; for(int i=len-1;i>=0;i--) sa[--buc[x[i]]]=i; for(int k=1;k<=len;k<<=1){ int p=0; for(int i=len-1;i>=len-k;i--) y[p++]=i; for(int i=0;i<len;i++) if(sa[i]>=k) y[p++]=sa[i]-k; for(int i=0;i<m;i++) buc[i]=0; for(int i=0;i<len;i++) buc[x[y[i]]]++; for(int i=1;i<m;i++) buc[i]+=buc[i-1]; for(int i=len-1;i>=0;i--) sa[--buc[x[y[i]]]]=y[i]; swap(x,y); p=1;x[sa[0]]=0; for(int i=1;i<len;i++){ if(y[sa[i-1]]==y[sa[i]]&&y[sa[i-1]+k]==y[sa[i]+k]) x[sa[i]]=p-1; else x[sa[i]]=p++; } if(p>=len) break; m=p; } for(int i=0;i<len;i++) ra[sa[i]]=i; int k=0; for(int i=0;i<len;i++){ if(ra[i]==0) { he[0]=0;continue; } if(k) k--; int j=sa[ra[i]-1]; while(s[i+k]==s[j+k]&&i+k<len&&j+k<len) k++; he[ra[i]]=k; } } int solve() { int ans=len-sa[0]; for(int i=1;i<len;i++){ ans+=(len-sa[i]-he[i]); } printf("%d ",ans); } int main() { int t; scanf("%d",&t); while(t--){ scanf("%s",s); len=strlen(s); m=200; get_suf(); solve(); } return 0; }