• 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;
    }
  • 相关阅读:
    解密JavaScript闭包
    如何实现JavaScript的Map和Filter函数?
    JavaScript函数重载
    ES6之Spread Operater拷贝对象
    C#中如果用await关键字来await一个为null的Task对象会抛出异常
    为何使用Microsoft SQL Server Management Studio连接Integration Services服务失败
    EF Core中如何正确地设置两张表之间的关联关系
    EF Core中外键关系的DeleteBehavior介绍(转自MSDN)
    SQL Server下ADO.NET 怎么获取数据库SQL语句INSERT,UPDATE,DELETE了多少行数据
    ASP.NET Core Middleware (转载)
  • 原文地址:https://www.cnblogs.com/jungu/p/13339327.html
Copyright © 2020-2023  润新知