模板
1 struct SuffixArray{ 2 int sa[maxn];//排名为i的后缀的起始下标 3 int Rank[maxn];//起始下标为i的后缀排名 4 int height[maxn];//排名为i和i-1的最长公共前缀 5 int wa[maxn],wb[maxn],wv[maxn],ws[maxn]; 6 7 int cmp(int *r, int a,int b,int l){//双关键字排序的比较 8 return r[a]==r[b] && r[a+l]==r[b+l]; 9 } 10 11 void da(int *r,int n,int m){ 12 ///r表示原数组,sa表示排名为i的下标,n表示r的大小+1,m表示字符的范围 13 ///注意使用时如果r的大小为n,那么应传入n+1 14 //x为第一关键字,y为第二关键字 15 int i,k,p,*x = wa,*y = wb,*t; 16 //长度为1时的基数排序 17 for(i=0;i<m;i++) ws[i] = 0; 18 for(i=0;i<n;i++) ws[x[i] = r[i]] ++; 19 for(i=0;i<m;i++) ws[i] += ws[i-1]; 20 for(i=n-1;i>=0;i--) sa[-- ws[x[i]]] = i; 21 //主要循环,k倍增 22 for(k=1,p=1; p<n; k*=2, m=p){ 23 //以下两行代码实现了对第二关键字的排序 24 for(p=0,i=n-k;i<n;i++) y[p++] = i; 25 for(i=0;i<n;i++){ 26 if(sa[i] >= k){ 27 y[p++] = sa[i] - k; 28 } 29 } 30 //提取出每个子串的第一关键字 31 for(i=0;i<n;i++){ 32 wv[i] = x[y[i]]; 33 } 34 //基数排序 35 for(i=0;i<m;i++) ws[i]=0; 36 for(i=0;i<n;i++) ws[wv[i]]++; 37 for(i=1;i<m;i++) ws[i]+=ws[i-1]; 38 for(i=n-1;i>=0;i--) sa[--ws[wv[i]]]=y[i]; 39 t=x,x=y,y=t; 40 for(p=1,x[sa[0]]=0,i=1;i<n;i++) 41 x[sa[i]]=cmp(y,sa[i-1],sa[i],k)?p-1:p++; 42 } 43 } 44 45 //求rank数组与height数组 46 void cal(int *r,int n){ 47 ///此处传入n即可 48 int i,j,k=0; 49 for(i=1;i<=n;i++) Rank[sa[i]] = i; 50 for(i=0;i<n;i++){ 51 if(k > 0) k--; 52 j=sa[Rank[i]-1]; 53 while(r[i+k] == r[j+k]) k++; 54 height[Rank[i]] = k; 55 } 56 57 //for(i=0;i<n;height[Rank[i++]]=k) 58 //for(k?k--:0,j=sa[Rank[i]-1];r[i+k]==r[j+k];k++); 59 } 60 61 /*使用方法 62 da(r,n+1,m); 63 cal(r,n);*/ 64 }SA;