https://vjudge.net/problem/SPOJ-DISUBSTR
题意:
给定一个字符串,求不相同的子串的个数。
思路:
1 #include<iostream> 2 #include<algorithm> 3 #include<cstring> 4 #include<cstdio> 5 #include<vector> 6 #include<stack> 7 #include<queue> 8 #include<cmath> 9 #include<map> 10 #include<set> 11 using namespace std; 12 typedef long long ll; 13 typedef pair<int,int> pll; 14 const int INF = 0x3f3f3f3f; 15 const int maxn=1000+5; 16 17 int n; 18 char s[maxn]; 19 int sa[maxn],t[maxn],t2[maxn],c[maxn]; 20 int Rank[maxn],height[maxn]; 21 22 void build_sa(int m) 23 { 24 int *x=t,*y=t2; 25 //基数排序 26 for(int i=0;i<m;i++) c[i]=0; 27 for(int i=0;i<n;i++) c[x[i]=s[i]]++; 28 for(int i=1;i<m;i++) c[i]+=c[i-1]; 29 for(int i=n-1;i>=0;i--) sa[--c[x[i]]]=i; 30 for(int k=1;k<=n;k<<=1) 31 { 32 int p=0; 33 //直接利用sa数组排序第二关键字 34 for(int i=n-k;i<n;i++) y[p++]=i; 35 for(int i=0;i<n;i++) if(sa[i]>=k) y[p++]=sa[i]-k; 36 //基数排序第一关键字 37 for(int i=0;i<m;i++) c[i]=0; 38 for(int i=0;i<n;i++) c[x[y[i]]]++; 39 for(int i=1;i<m;i++) c[i]+=c[i-1]; 40 for(int i=n-1;i>=0;i--) sa[--c[x[y[i]]]]=y[i]; 41 //根据sa和y计算新的x数组 42 swap(x,y); 43 p=1; 44 x[sa[0]]=0; 45 for(int i=1;i<n;i++) 46 x[sa[i]]=y[sa[i-1]]==y[sa[i]]&&y[sa[i-1]+k]==y[sa[i]+k]?p-1:p++; 47 if(p>=n) 48 break; 49 m=p; //下次基数排序的最大值 50 } 51 } 52 53 void getHeight(int n) 54 { 55 int i,j,k=0; 56 for(i=1;i<=n;i++) Rank[sa[i]]=i; 57 for(i=0;i<n;i++) 58 { 59 if(k) k--; 60 int j=sa[Rank[i]-1]; 61 while(s[i+k]==s[j+k]) k++; 62 height[Rank[i]]=k; 63 } 64 } 65 66 int main() 67 { 68 //freopen("in.txt","r",stdin); 69 int T; 70 scanf("%d",&T); 71 while(T--) 72 { 73 scanf("%s",s); 74 n=strlen(s); 75 s[n]='0'; 76 n++; 77 build_sa(128); 78 getHeight(n-1); 79 int ans=(n-1)*n/2; 80 for(int i=1;i<n;i++) 81 ans-=height[i]; 82 printf("%d\n",ans); 83 } 84 return 0; 85 }