1. 程式人生 > 實用技巧 >2020牛客多校 第一場 A

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; }