whu1564 求字符串的所有循环子串第k大 :后缀数组模板
原题少了当前的字符,不过并无差别
利用sa数组可以很方便的求出来==
1 #include<stdio.h> 2 #include<string.h> 3 #include<algorithm> 4 using namespace std; 5 struct SA{ 6 int sa[2000005],t[2000005],t2[2000005],c[2000005],n,m; 7 void build_sa(char *s,int _n){ 8 n=2*_n+1; m=128; 9 int i,*x=t,*y=t2; 10 //基数排序 11 for (i=0;i<m;i++) c[i]=0; 12 for (i=0;i<n;i++) c[x[i]=s[i]]++; 13 for (i=1;i<m;i++) c[i]+=c[i-1]; 14 for (i=n-1;i>=0;i--) sa[--c[x[i]]]=i; 15 for (int k=1;k<=n;k<<=1){ 16 int p=0; 17 //直接利用sa数组排序第二关键字 18 for (i=n-k;i<n;i++) y[p++]=i; 19 for (i=0;i<n;i++) if (sa[i]>=k) y[p++]=sa[i]-k; 20 //基数排序第一关键字 21 for (i=0;i<m;i++) c[i]=0; 22 for (i=0;i<n;i++) c[x[y[i]]]++; 23 for (i=0;i<m;i++) c[i]+=c[i-1]; 24 for (i=n-1;i>=0;i--) sa[--c[x[y[i]]]]=y[i]; 25 //根据sa和y数组计算新的x数组 26 swap(x,y); 27 p=1; x[sa[0]]=0; 28 for (i=1;i<n;i++) 29 x[sa[i]]=y[sa[i-1]]==y[sa[i]]&&y[sa[i-1]+k]==y[sa[i]+k]?p-1:p++; 30 if (p>=n) break; 31 m=p;//下次基数排序的最大值 32 } 33 } 34 int solve(int k){ 35 int i,cnt=0; 36 for (i=0;i<n;i++) 37 { 38 if (sa[i]<=n/2&&sa[i]!=0) cnt++; 39 if (cnt==k) return sa[i]; 40 } 41 } 42 }H; 43 char s[2000005]; 44 int main() 45 { 46 int i,n,k; 47 while (~scanf("%d%d",&n,&k)) 48 { 49 scanf("%s",s); 50 for (i=0;i<n;i++) s[i+n]=s[i]=s[i]-'0'; 51 s[2*n]=10; 52 H.build_sa(s,n); 53 printf("%d\n",H.solve(k)); 54 } 55 return 0; 56 }
题目链接:http://acm.whu.edu.cn/land/problem/detail?problem_id=1564