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;
}
原文地址:https://www.cnblogs.com/jungu/p/13339327.html