P3809 【模板】后缀排序
1 #include <bits/stdc++.h>
2 using namespace std;
3 const int maxn = 1e6+5;
4 char s[maxn];
5 int sa[maxn], t[maxn], t2[maxn], c[maxn];
6 int n;
7 //构造字符串s的后缀数组, 每个字符值必须为0 ~ m-1
8 void build_sa(int m) {
9 int *x = t, *y = t2;
10 //基数排序
11 for(int i = 0; i < m; i++) c[i] = 0;
12 for(int i = 0; i < n; i++) c[x[i] = s[i]]++;
13 for(int i = 1; i < m; i++) c[i] += c[i-1];
14 for(int i = n-1; i >= 0; i--) sa[--c[x[i]]] = i;
15 for(int k = 1; k <= n; k <<= 1) {
16 int p = 0;
17 //直接利用sa数组排序第二关键字
18 for(int i = n-k; i < n; i++) y[p++] = i;
19 for(int i = 0; i < n; i++) if(sa[i] >= k) y[p++] = sa[i] - k;
20 //基数排序第一关键字
21 for(int i = 0; i < m; i++) c[i] = 0;
22 for(int i = 0; i < n; i++) c[x[y[i]]]++;
23 for(int i = 1; i < m; i++) c[i] += c[i-1];
24 for(int i = n-1; i>= 0; i--) sa[--c[x[y[i]]]] = y[i];
25 //根据sa和y数组计算新的x数组
26 swap(x, y);
27 p = 1;
28 x[sa[0]] = 0;
29 for(int i = 1; i < n; i++)
30 x[sa[i]] = (y[sa[i-1]] == y[sa[i]] && y[sa[i-1]+k] == y[sa[i]+k] ? p-1 : p++);
31 if(p >= n) break;
32 m = p;
33 }
34 }
35 int main() {
36 scanf("%s",s); n = strlen(s);
37 build_sa(123);
38 printf("%d",sa[0]+1);
39 for (int i = 1; i < n; i++)
40 printf(" %d",sa[i]+1);
41 printf("\n");
42 return 0;
43 }