hdu3518 后缀数组标准模板:出现两次及以上子串数目
字符串最后切记别忘了加上一个与前面不同的小标志!!
然后此题还是利用height函数把每一个所枚举的长度为i的重复串个数计算出来,然后多少个不同的ans++
1 #include<stdio.h> 2 #include<string.h> 3 #include<algorithm> 4 using namespace std; 5 char s[200005]; 6 7 int sa[200005],t[200005],t2[200005],c[200005]; 8 void build_sa(int m,int n) 9 { 10 int i,*x=t,*y=t2; 11 //基数排序 12 for (i=0;i<m;i++) c[i]=0; 13 for (i=0;i<n;i++) c[x[i]=s[i]]++; 14 for (i=1;i<m;i++) c[i]+=c[i-1]; 15 for (i=n-1;i>=0;i--) sa[--c[x[i]]]=i; 16 for (int k=1;k<=n;k<<=1) 17 { 18 int p=0; 19 //直接利用sa数组排序第二关键字 20 for (i=n-k;i<n;i++) y[p++]=i; 21 for (i=0;i<n;i++) if (sa[i]>=k) y[p++]=sa[i]-k; 22 //基数排序第一关键字 23 for (i=0;i<m;i++) c[i]=0; 24 for (i=0;i<n;i++) c[x[y[i]]]++; 25 for (i=0;i<m;i++) c[i]+=c[i-1]; 26 for (i=n-1;i>=0;i--) sa[--c[x[y[i]]]]=y[i]; 27 //根据sa和y数组计算新的x数组 28 swap(x,y); 29 p=1; x[sa[0]]=0; 30 for (i=1;i<n;i++) 31 x[sa[i]]=y[sa[i-1]]==y[sa[i]]&&y[sa[i-1]+k]==y[sa[i]+k]?p-1:p++; 32 if (p>=n) break; 33 m=p;//下次基数排序的最大值 34 } 35 } 36 37 int _rank[200005],height[200005]; 38 void getHeight(int n) 39 { 40 int i,j,k=0; 41 for (i=0;i<=n;i++) _rank[sa[i]]=i; 42 for (i=0;i<n;i++) 43 { 44 if (k) k--; 45 j=sa[_rank[i]-1]; 46 while (s[i+k]==s[j+k]) k++; 47 height[_rank[i]]=k; 48 } 49 } 50 51 int main() 52 { 53 int ans,j,i,maxx,minx,n; 54 while (~scanf("%s",s)&&s[0]!='#') 55 { 56 n=strlen(s); s[n]='0'; 57 build_sa(300,n+1); getHeight(n); 58 ans=0; 59 for (i=1;i<=n/2;i++) 60 { 61 minx=1200; maxx=-1; 62 for (j=1;j<=n;j++) 63 if (height[j]>=i) 64 { 65 if (sa[j-1]>maxx) maxx=sa[j-1]; 66 if (sa[j-1]<minx) minx=sa[j-1]; 67 if (sa[j]>maxx) maxx=sa[j]; 68 if (sa[j]<minx) minx=sa[j]; 69 } 70 else{ 71 if (maxx-minx>=i) ans++; 72 minx=1200; maxx=-1; 73 } 74 if (maxx-minx>=i) ans++; 75 } 76 printf("%d\n",ans); 77 } 78 }