2020牛客多校 第一场 A
题意:给定一个字符串,根据题目要求将每个后缀的b函数进行排序,从小到大输出对应后缀的起始位
思路:比赛的时候没推出结论。引用题解结论,定义$c[i] = j - i$,$j$为索引$i$后面最近的索引使得$s[i] == s[j]$,就相当于逆序求出$c$函数。这时得到的数组就是后缀排序就是实际字符串$b$函数从大到小的排序。由于答案是从小到大的排序,因此可求对每个$c[i]$补位,这时的后缀排序就是$b$函数从小到大的排序。由此用后缀数组对$c$求$sa$即可。(还要将每个$c[i] + 1$,序列后面额外添一个$0$)
Code:
#pragma GCC optimize(3) #pragma GCC optimize(2) #include <map> #include <set> #include <array> #include <queue> #include <stack> #include <vector> #include <cstdio> #include <cstring> #include <sstream> #include <iostream> #include <stdlib.h> #include <algorithm> #include <unordered_map> using namespace std; typedef long long ll; typedef pair<int, int> PII; #define Time (double)clock() / CLOCKS_PER_SEC #define sd(a) scanf("%d", &a) #define sdd(a, b) scanf("%d%d", &a, &b) #define slld(a) scanf("%lld", &a) #define slldd(a, b) scanf("%lld%lld", &a, &b) const int N = 1e5 + 50; const int mod = 998244353; int n, m; char s[N]; int sa[N], x[N], y[N], num[N]; void qsort() { for (int i = 0; i < m; i++) num[i] = 0; for (int i = 0; i < n; i++) num[x[i]]++; for (int i = 1; i < m; i++) num[i] += num[i - 1]; for (int i = n - 1; i >= 0; i--) sa[--num[x[y[i]]]] = y[i]; } void solve() { qsort(); for (int j = 1, p = 1; p < n; j <<= 1, m = p) { p = 0; for (int i = n - j; i < n; i++) y[p++] = i; for (int i = 0; i < n; i++) if (sa[i] >= j) y[p++] = sa[i] - j; qsort(); for (int i = 0; i < n; i++) y[i] = x[i]; x[sa[0]] = 0, p = 1; for (int i = 1; i < n; i++) x[sa[i]] = (y[sa[i]] == y[sa[i - 1]] && y[sa[i] + j] == y[sa[i - 1] + j]) ? p - 1 : p ++; } } int main() { #ifdef ONLINE_JUDGE #else freopen("/home/jungu/code/in.txt", "r", stdin); freopen("/home/jungu/code/out.txt", "w", stdout); // freopen("/home/jungu/code/out.txt","w",stdout); #endif ios::sync_with_stdio(false); cin.tie(0), cout.tie(0); while (cin >> n) { cin >> s; int a = n, b = n; for (int i = n - 1; i >= 0; i--) { y[i] = i; if (s[i] == 'a') { if (a == n) { x[i] = 1; } else { x[i] = n - a + i + 1; } a = i; } else { if (b == n) { x[i] = 1; } else { x[i] = n - b + i + 1; } b = i; } } x[n] = 0, y[n] = n; n ++; m = n + 1; solve(); for (int i = 1; i < n; i++) { cout << sa[i] + 1 << " "; } cout << endl; } return 0; }