P3809 【模板】后缀排序

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 }

 

posted @ 2019-10-23 18:42  麻辣猪仔  阅读(165)  评论(0编辑  收藏  举报