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 <= 1000
Output
For each test case output one number saying the number of distinct substrings.
Example
Sample Input:
2
CCCCC
ABABA
Sample Output:
5
9
Explanation for the testcase with string ABABA:
len=1 : A,B
len=2 : AB,BA
len=3 : ABA,BAB
len=4 : ABAB,BABA
len=5 : ABABA
Thus, total number of distinct substrings is 9.
题目大意: 给你一个字符串,问互补相同的字串有几个。
我们知道每一个字串都是后缀的前缀,所以我们只要先求出后缀数组,然后对于排名相邻的两个串,比如排名为第i的串,他提供的前缀数量是len-sa[i],但由于有H[i]个和排名第i-1的是一样的,所以我们要减去h[i],这样扫一遍就可以了。
1 #include<bits/stdc++.h> 2 using namespace std; 3 int const N=1000+3; 4 int wa[N<<1],wb[N<<1],wv[N],rk[N],h[N],num[N],sa[N]; 5 char s[N]; 6 int cmp(int *r,int x,int y,int z){ 7 return r[x]==r[y] && r[x+z]==r[y+z]; 8 } 9 void build_sa(char *r,int *sa,int n,int m){ 10 int i,j,p,*x=wa,*y=wb; 11 for(i=0;i<m;i++) num[i]=0; 12 for(i=0;i<n;i++) num[x[i]=r[i]]++; 13 for(i=1;i<m;i++) num[i]+=num[i-1]; 14 for(i=n-1;i>=0;i--) sa[--num[x[i]]]=i; 15 for(j=1,p=1;p<n;m=p){ 16 for(p=0,i=n-j;i<n;i++) y[p++]=i; 17 for(i=0;i<n;i++) if(sa[i]>=j) y[p++]=sa[i]-j; 18 for(i=0;i<m;i++) num[i]=0; 19 for(i=0;i<n;i++) num[wv[i]=x[y[i]]]++; 20 for(i=1;i<m;i++) num[i]+=num[i-1]; 21 for(i=n-1;i>=0;i--) sa[--num[wv[i]]]=y[i]; 22 swap(x,y); 23 for(i=1,p=1,x[sa[0]]=0;i<n;i++) 24 x[sa[i]]=cmp(y,sa[i],sa[i-1],j)? p-1:p++; 25 } 26 for(i=0;i<n;i++) rk[i]=x[i]; 27 } 28 void build_h(char *r,int *sa,int n){ 29 int k=0; 30 for(int i=0;i<n;i++){ 31 if(k) k--; 32 int j=sa[rk[i]-1]; 33 while (r[i+k]==r[j+k]) k++; 34 h[rk[i]]=k; 35 } 36 } 37 void solve(int n){ 38 int ans=0; 39 for(int i=1;i<=n;i++){ 40 int num=n-sa[i]; 41 ans+=num-h[i]; 42 } 43 printf("%d\n",ans); 44 } 45 int main(){ 46 int cas; 47 scanf("%d",&cas); 48 while (cas--){ 49 scanf("%s",s); 50 int len=strlen(s); 51 build_sa(s,sa,len+1,130); 52 build_h(s,sa,len); 53 solve(len); 54 } 55 return 0; 56 }