大家都知道后缀数组很cao dan,需要给予基数排序(时间复杂度:N*LogN)
下面带来N*Log2 N 的做法(然而并慢不了多少)
代码 30行,不要基数排序
1 int n,k,rank[MAX_N+1],tmp[MAX_N+1]; 2 //比较rank[i],rank[i+k]和rank[j],rank[j+k] 3 bool compare_sa{ 4 if(rank[i]!=rank[j])return rank[i]<rank[j]; 5 else { 6 int ri= i+k <= n ? rank[i+k] : -1; 7 int rj= j+k <= n ? rank[j+k] : -1; 8 return ri<rj; 9 } 10 } 11 // 正题 计算字符串S的后缀数组 12 void con_sa(strint s,int *sa){ 13 n=s.length(); 14 // 初始长度为1 rank直接取字符编码 15 for(int i=0;i<=n;i++){ 16 sa[i]=i; 17 rank[i]= i<n ? s[i] : -1; 18 } 19 // 利用长度为K的排序的结果对长度为2K的进行排序 20 for(int k=1;k<=n;k *= 2){ 21 sort(sa,sa+n+1,compare_sa); 22 tmp[sa[0]]=0; 23 for(int i=1;i<=n;i++){ 24 tmp[sa[i]]=tmp[sa[i-1]] + 25 (compare_sa(sa[i-1],sa[i]) ? 1 : 0); 26 } 27 for(int i=0;i<=n;i++) 28 rank[i]=tmp[i]; 29 } 30 }