各个数组含义
sa[] 名次-》位置
_rank[] 位置-》名次
tp [] 第二关键字 名次-》位置
height[] 两个排名相邻后缀最长公共前缀
性质1 两个后缀(i,j)的最大公共前缀=min (height[_rank[i]+1].....height[_rank[j]] ) (假设排名_rank[i]<_rank[j])
性质2 h[i]>=h[i-1]-1 (h[i] i位置的后缀数组和它前一名的最长公共前缀)
void resort () {//基数排序 for (int i=0;i<=m;i++) tax[i]=0; for (int i=1;i<=n;i++) tax[ _rank[i] ]++; for (int i=1;i<=m;i++) tax[i]+=tax[i-1]; for (int i=n;i>=1;i--) sa[tax[_rank[tp[i]]]--]=tp[i]; } void build_sa() { for (int i=1;i<=n;i++) { _rank[i]=a[i]; tp[i]=i; } m=27; resort();// 初始化 for (int w=1,p=1,i;p<n;w+=w,m=p) { // 第二关键字排序 for (p=0,i=n-w+1;i<=n;i++) tp[++p]=i; for (i=1;i<=n;i++) if (sa[i]>w) tp[++p]=sa[i]-w; // 第一关键字排序 resort(); // 根据sa[]求_rank[] swap(_rank,tp); _rank[sa[1]]=p=1; for (i=2;i<=n;i++) { if (tp[sa[i-1]]==tp[sa[i]]&&tp[sa[i-1]+w]==tp[sa[i]+w])
_rank[sa[i]]=p; else
_rank[sa[i]]=(++p); } } return ; } void build_height() { int k=0;// height数组 for (int i=1;i<=n;i++) { if (k) k--; int j=sa[_rank[i]-1]; while (str[i+k]==str[j+k]) k++; height[_rank[i]]=k; } return ; }