模板
#include<cstdio> #include<algorithm> #include<cstring> using namespace std; #define N 100001 int sa[N],t[N],t2[N],tong[N],n; char s[N]; inline bool cmp(int *y,int i,int k) { return (y[sa[i-1]]==y[sa[i]])&&((sa[i-1]+k>=n?-1:y[sa[i-1]+k])==(sa[i]+k>=n?-1:y[sa[i]+k])); } //构造字符串s的后缀数组,每个字符值必须为0~m-1,字符串下标为0~n-1 void build_sa(int range) { int *x=t,*y=t2; //基数排序 memset(tong,0,sizeof(int)*range);//清空桶 for(int i=0;i<n;++i) tong[x[i]=s[i]]++;//把s拷贝到x中,之后插入桶 for(int i=1;i<range;++i) tong[i]+=tong[i-1];//将桶处理成前缀和 for(int i=n-1;i>=0;--i) sa[--tong[x[i]]]=i; for(int k=1;k<=n;k<<=1) { int p=0; //直接利用sa数组排序第二关键字 for(int i=n-k;i<n;++i) y[p++]=i; for(int i=0;i<n;++i) if(sa[i]>=k) y[p++]=sa[i]-k; //基数排序第一关键字 memset(tong,0,sizeof(int)*range); for(int i=0;i<n;++i) tong[x[y[i]]]++; for(int i=0;i<range;++i) tong[i]+=tong[i-1]; for(int i=n-1;i>=0;--i) sa[--tong[x[y[i]]]]=y[i]; //根据sa和y数组计算新的x数组 swap(x,y); p=1; x[sa[0]]=0; for(int i=1;i<n;++i) x[sa[i]]= cmp(y,i,k) ? p-1 : p++; if(p>=n) break; range=p; } } int rank[N],lcp[N]; void get_lcp() { int k=0; for(int i=0;i<n;++i) rank[sa[i]]=i; for(int i=0;i<n;++i) if(rank[i]) { if(k) --k; int j=sa[rank[i]-1]; while(s[i+k]==s[j+k]) ++k; lcp[rank[i]]=k; } } int main() { scanf("%s",s); n=strlen(s); build_sa('z'+1); for(int i=0;i<n;++i) printf("%d ",sa[i]+1); puts(""); if(n>1) get_lcp(); for(int i=1;i<n;++i) printf("%d ",lcp[i]); return 0; }