洛谷P3809 后缀排序【后缀数组】【模板】

题目背景

这是一道模板题。

题目描述

读入一个长度为 nn 的由大小写英文字母或数字组成的字符串,请把这个字符串的所有非空后缀按字典序从小到大排序,然后按顺序输出后缀的第一个字符在原串中的位置。位置编号为 11 到 nn。

输入输出格式

输入格式:

 

一行一个长度为 nn 的仅包含大小写英文字母或数字的字符串。

 

输出格式:

 

一行,共n个整数,表示答案。

 

输入输出样例

输入样例#1: 复制
ababa
输出样例#1: 复制
5 3 1 4 2

说明

n <= 10^6n<=106

 

 

后缀数组知识点详解:

https://www.cnblogs.com/wyboooo/p/9854468.html

 1 #include <iostream>
 2 #include <set>
 3 #include <cmath>
 4 #include <stdio.h>
 5 #include <cstring>
 6 #include <algorithm>
 7 #include <vector>
 8 #include <queue>
 9 #include <map>
10 using namespace std;
11 typedef long long LL;
12 #define inf 0x7f7f7f7f
13 
14 const int maxn = 1e6 + 5;
15 char s[maxn];
16 int n;
17 int sa[maxn];
18 int t1[maxn], t2[maxn], c[maxn];
19 int rnk[maxn], height[maxn];
20 
21 void build_sa(char s[], int n, int m)
22 {
23     int i, j, p, *x = t1, *y = t2;
24     for(i = 0; i < m; i++)c[i] = 0;
25     for(i = 0; i < n; i++)c[x[i] = s[i] - '0']++;
26     for(i = 1; i < m; i++)c[i] += c[i - 1];
27     for(i = n - 1; i >= 0; i--)sa[--c[x[i]]] = i;
28     for(j = 1; j <= n; j <<= 1){
29         p = 0;
30         for(i = n - j; i < n; i++)y[p++] = i;
31         for(i = 0; i < n; i++)if(sa[i] >= j) y[p++] = sa[i] - j;
32         for(i = 0; i < m; i++)c[i] = 0;
33         for(i = 0; i < n; i++)c[x[y[i]]]++;
34         for(i = 1; i < m; i++)c[i] += c[i - 1];
35         for(i = n - 1; i >= 0; i--)sa[--c[x[y[i]]]] = y[i];
36         swap(x, y);
37         p = 1;
38         x[sa[0]] = 0;
39         for(i = 1; i < n; i++)
40             x[sa[i]] = y[sa[i - 1]] == y[sa[i]] && y[sa[i - 1] + j] == y[sa[i] + j] ? p - 1:p++;
41         if(p >= n)break;
42         m = p;
43     }
44 }
45 
46 int main()
47 {
48     scanf("%s", s);
49     n = strlen(s);
50     build_sa(s, n, 200);
51     printf("%d", sa[0] + 1);
52     for(int i = 1; i < n; i++){
53         printf(" %d", sa[i] + 1);
54     }
55     printf("\n");
56     return 0;
57 }

 

posted @ 2018-10-26 14:54  wyboooo  阅读(211)  评论(0编辑  收藏  举报