Description
Given a string, we need to find the total number of its distinct substrings.
T- number of test cases. T<=20;
Each test case consists of one string, whose length is <= 1000
For each test case output one number saying the number of distinct substrings.
Sample Input:
2
CCCCC
ABABA
Sample Output:
5
9
这个也是为数不多看懂做法并且明白的题之一==
如果不算重复的个数,长度为n的字符串可以组成的子串个数是n+(n-1)……+1个 ,(从一开始枚举),联想length[]的定义:排名相近的两个子串的最长公共前缀长度,那既然都是公共了,就多算了这些子串==
/******************* spoj694. Distinct Substrings 2016.2.22 3789 0 C++ (g++ 4.9.2) 1678 *******************/ #include <iostream> #include<cstdio> #include<cstring> using namespace std; #define MAXN 10005 int t1[MAXN],t2[MAXN],c[MAXN]; bool cmp(int *r,int a,int b,int l) { return r[a]==r[b]&&r[a+l]==r[b+l]; } void da(int str[],int sa[],int rank[],int height[],int n,int m) { n++; int i,j,p,*x=t1,*y=t2; for(i=0;i<m;i++) c[i]=0; for(i=0;i<n;i++) c[x[i]=str[i]]++; for(i=1;i<m;i++) c[i]+=c[i-1]; for(i=n-1;i>=0;i--) sa[--c[x[i]]]=i; for(j=1;j<=n;j<<=1) { p=0; for(i=n-j;i<n;i++) y[p++]=i; for(i=0;i<n;i++) if(sa[i]>=j) y[p++]=sa[i]-j; for(i=0;i<m;i++) c[i]=0; for(i=0;i<n;i++) c[x[y[i]]]++; for(i=1;i<m;i++) c[i]+=c[i-1]; for(i=n-1;i>=0;i--) sa[--c[x[y[i]]]]=y[i]; swap(x,y); p=1;x[sa[0]]=0; for(i=1;i<n;i++) x[sa[i]]=cmp(y,sa[i-1],sa[i],j)?p-1:p++; if(p>=n) break; m=p; } int k=0; n--; for(i=0;i<=n;i++) rank[sa[i]]=i; for(i=0;i<n;i++) { if(k) k--; j=sa[rank[i]-1]; while(str[i+k]==str[j+k]) k++; height[rank[i]]=k; } } char str[MAXN]; int r[MAXN],sa[MAXN],rank[MAXN],height[MAXN]; int main() { // freopen("cin.txt","r",stdin); int t; scanf("%d",&t); while(~scanf("%s",str)) { int n=strlen(str); for(int i=0;i<n;i++) r[i]=str[i]; r[n]=0; da(r,sa,rank,height,n,256); int ans=0; for(int i=1;i<=n;i++) { ans+=(n-i+1-height[i]); // printf("h=%d ",height[i]); } printf("%d\n",ans); } return 0; }