Sequence(后缀数组)

Description

Given a sequence, {A1, A2, …, An} which is guaranteed A1 > A2, …, An, you are to cut it into three sub-sequences and reverse them separately to form a new one which is the smallest possible sequence in alphabet order.

The alphabet order is defined as follows: for two sequence {A1, A2, …, An} and {B1, B2, …, Bn}, we say {A1, A2, …, An} is smaller than {B1, B2, …, Bn} if and only if there exists such i ( 1 ≤ i ≤ n) so that we have Ai < Bi and Aj = Bj for each j < i.

Input

The first line contains n. (n ≤ 200000)

The following n lines contain the sequence.

Output

output n lines which is the smallest possible sequence obtained.

Sample Input

5 10 1 2 3 4

Sample Output

1 10 2 4 3

Hint {10, 1, 2, 3, 4} -> {10, 1 | 2 | 3, 4} -> {1, 10, 2, 4, 3}

Source POJ Founder Monthly Contest – 2008.04.13, Yao Jinyu

首先将字符串翻转,求后缀数组,得到一个最小后缀,当然这个最小后缀的起始点应该在原串的倒数第二个位置之前,不然无法分成三段 然后对于剩下的字符串,相当于是要分成2份然后字典序最小,对于这个,我一开始想用最小表示法的那个线性方法来求,后来发现这样可能会出现不切分的情况,也就是这个字符串的字典序已经是最小的了 于是我把剩余字符串重复一次接到一起,,然后再求一次后缀数组,这样就求出了每一个字符串表示法的字典序排名,当然我们要的是字典序最小的而且位置在字符串倒数第一个位置之前的

/*************************************************************************> File Name: POJ3581.cpp> Author: ALex> Mail: zchao1995@gmail.com> Created Time: 2015年04月08日 星期三 10时15分12秒 ************************************************************************/;const double pi = acos(-1.0);const int inf = 0x3f3f3f3f;const double eps = 1e-15;LL;typedef pair <int, int> PLL;int xis[202000];int cnt;int Binsearch(int val){int l = 1, r = cnt, mid;while (l <= r){mid = (l + r) >> 1;if (xis[mid] == val){break;}else if (xis[mid] > val){r = mid – 1;}else{l = mid + 1;}}return mid;}class SuffixArray{public:N = 402000;int init[N];int X[N];int Y[N];int Rank[N];int sa[N];int height[N];int buc[N];int size;void clear(){size = 0;}void insert(int n){init[size++] = n;}bool cmp(int *r, int a, int b, int l){return (r[a] == r[b] && r[a + l] == r[b + l]);}void getsa(int m){init[size] = 0;int l, p, *x = X, *y = Y, n = size + 1;for (int i = 0; i < m; ++i){buc[i] = 0;}for (int i = 0; i < n; ++i){++buc[x[i] = init[i]];}for (int i = 1; i < m; ++i){buc[i] += buc[i – 1];}for (int i = n – 1; i >= 0; –i){sa[–buc[x[i]]] = i;}for (l = 1, p = 1; l <= n && p < n; m = p, l *= 2){p = 0;for (int i = n – l; i < n; ++i){y[p++] = i;}for (int i = 0; i < n; ++i){if (sa[i] >= l){y[p++] = sa[i] – l;}}for (int i = 0; i < m; ++i){buc[i] = 0;}for (int i = 0; i < n; ++i){++buc[x[y[i]]];}for (int i = 1; i < m; ++i){buc[i] += buc[i – 1];}for (int i = n – 1; i >= 0; –i){sa[–buc[x[y[i]]]] = y[i];}int i;for (swap(x, y), x[sa[0]] = 0, p = 1, i = 1; i < n; ++i){x[sa[i]] = cmp(y, sa[i – 1], sa[i], l) ? p – 1 : p++;}}}void getheight(){int h = 0, n = size;for (int i = 0; i <= n; ++i){Rank[sa[i]] = i;}height[0] = 0;for (int i = 1; i < n; ++i){if (h > 0){–h;}int j = sa[Rank[i] – 1];for (; i + h < n && j + h < n && init[i + h] == init[j + h]; ++h);height[Rank[i] – 1] = h;}}}SA;int arr[202000];int main(){int n;scanf(“%d”, &n);cnt = 0;SA.clear();for (int i = 0; i < n; ++i){scanf(“%d”, &arr[i]);xis[++cnt] = arr[i];}if (n <= 3){for (int i = 0; i < n; ++i){printf(“%d\n”, arr[i]);}return 0;}sort(xis + 1, xis + 1 + cnt);cnt = unique(xis + 1, xis + 1 + cnt) – xis – 1;for (int i = n – 1; i >= 0; –i){int val = Binsearch(arr[i]);SA.insert(val);}SA.getsa(cnt + 1);SA.getheight();int mins = inf, pos;for (int i = 2; i < n; ++i){if (SA.Rank[i] < mins){mins = SA.Rank[i];pos = i;}}SA.clear();for (int i = n – pos – 1; i >= 0; –i){printf(“%d\n”, arr[i]);}for (int i = n – 1; i > n – pos – 1; –i){int val = Binsearch(arr[i]);SA.insert(val);}for (int i = n – 1; i >= n – pos; –i){int val = Binsearch(arr[i]);SA.insert(val);}SA.getsa(cnt + 1);SA.getheight();mins = inf;int s;for (int i = 1; i < pos; ++i){if (SA.Rank[i] < mins){mins = SA.Rank[i];s = i;}}for (int i = n – s – 1; i >= n – pos ; –i){printf(“%d\n”, arr[i]);}for (int i = n – 1; i > n – s – 1; –i){printf(“%d\n”, arr[i]);}return 0;}

深重如溺入蓝色的海洋,无法呼吸。

Sequence(后缀数组)

相关文章:

你感兴趣的文章:

标签云: