#include<iostream>#include<cstring>#include<algorithm>usingnamespace std;constint N =1000010;int n, m;char s[N];int sa[N];//排名第i位的是第几个后缀int rk[N];//第i个后缀排名是多少int height[N];//sa[i]和sa[i-1]的最长公共前缀int x[N], y[N], c[N];voidget_sa(){for(int i =1; i <= n; i ++) c[x[i]= s[i]]++;for(int i =2; i <= m; i ++) c[i]+= c[i -1];for(int i = n; i; i --) sa[c[x[i]]--]= i;for(int k =1; k <= n; k <<=1){int num =0;for(int i = n - k +1; i <= n; i ++) y[++ num]= i;for(int i =1; i <= n; i ++)if(sa[i]> k)
y[++ num]= sa[i]- k;for(int i =1; i <= m; i ++) c[i]=0;for(int i =1; i <= n; i ++) c[x[i]]++;for(int i =2; i <= m; i ++) c[i]+= c[i -1];for(int i = n; i; i --) sa[c[x[y[i]]]--]= y[i], y[i]=0;swap(x, y);
x[sa[1]]=1, num =1;for(int i =2; i <= n; i ++)
x[sa[i]]=(y[sa[i]]== y[sa[i -1]]&& y[sa[i]+ k]== y[sa[i -1]+ k])? num :++ num;if(num == n)break;
m = num;}}voidget_height(){for(int i =1; i <= n; i ++) rk[sa[i]]= i;for(int i =1, k =0; i <= n; i ++){if(rk[i]==1)continue;if(k) k --;int j = sa[rk[i]-1];while(i + k <= n && j + k <= n && s[i + k]== s[j + k]) k ++;
height[rk[i]]= k;}}intmain(){scanf("%s", s +1);
n =strlen(s +1), m =122;get_sa();get_height();for(int i =1; i <= n; i ++)printf("%d ", sa[i]);puts("");for(int i =1; i <= n; i ++)printf("%d ", height[i]);puts("");return0;}
作者:yxc
链接:https://www.acwing.com/activity/content/code/content/571844/
来源:AcWing
后缀数组模板#include <iostream>#include <cstring>#include <algorithm>using namespace std;const int N = 1000010;int n, m;char s[N];int sa[N];//排名第i位第是第几个后缀int rk[N];//第i个后缀排名是多少int height[N];//sa[i]和sa[i-1]第最长公共前缀int x[N], y[N], c