zoukankan      html  css  js  c++  java
  • Infinite Fraction Path (后缀数组)

    题意

    source

    思路

    求每一位开始的字符串中字典序最小的字符串,容易想到用后缀数组。预处理出每一位开始跳2的幂次后位置,然后稍微修改一下后缀数组模板倍增部分即可。
    使用普通排序的版本会T,得用计数排序。

    #include <iostream>
    #include <algorithm>
    
    // #define endl '
    '
    #define IOS std::ios::sync_with_stdio(0); cin.tie(0); cout.tie(0)
    #define FILE freopen(".//data_generator//in.txt","r",stdin),freopen("res.txt","w",stdout)
    #define FI freopen(".//data_generator//in.txt","r",stdin)
    #define FO freopen("res.txt","w",stdout)
    #define mp make_pair
    #define seteps(N) fixed << setprecision(N) 
    typedef long long ll;
    
    using namespace std;
    /*-----------------------------------------------------------------*/
    
    ll gcd(ll a, ll b) {return b ? gcd(b, a % b) : a;}
    #define INF 0x3f3f3f3f3f3f3f3f
    
    using namespace std;
    
    const int N = 2e5 + 10;
    int sa[N], rk[N], oldrk[N], id[N], cnt[N];
    int arr[N];
    int up[25][N];
    
    int main() {
        // IOS;
        int cas = 0;
        int t;
        cin >> t;
        while(t--) {
            int n;
            cin >> n;
            int m = max(10, n);
            for(int i = 0; i < n; i++) {
                char ch;
                cin >> ch;
                arr[i + 1] = ch - '0';
                up[0][i + 1] = (1ll * i * i + 1) % n + 1;
            }
            for(int i = 1; (1 << i) <= n; i++) {
                for(int j = 1; j <= n; j++) {
                    up[i][j] = up[i - 1][up[i - 1][j]];
                }
            }
            for(int i = 1; i <= n; i++) {
                rk[i] = arr[i] + 1;
            }
            
            for(int i = 1; i <= m; i++) cnt[i] = 0;
            for (int i = 1; i <= n; ++i) ++cnt[rk[i]];
            for (int i = 1; i <= m; ++i) cnt[i] += cnt[i - 1];
            for (int i = n; i >= 1; --i) sa[cnt[rk[i]]--] = i;
    
            for (int po = 0, w = 1; w < n; w <<= 1, po++) {
              for(int i = 1; i <= m; i++) cnt[i] = 0;
    
              for (int i = 1; i <= n; ++i) id[i] = sa[i];
              for (int i = 1; i <= n; ++i) ++cnt[rk[up[po][id[i]]]];
              for (int i = 1; i <= m; ++i) cnt[i] += cnt[i - 1];
              for (int i = n; i >= 1; --i) sa[cnt[rk[up[po][id[i]]]]--] = id[i];
              for(int i = 1; i <= m; i++) cnt[i] = 0;
    
              for (int i = 1; i <= n; ++i) id[i] = sa[i];
              for (int i = 1; i <= n; ++i) ++cnt[rk[id[i]]];
              for (int i = 1; i <= m; ++i) cnt[i] += cnt[i - 1];
              for (int i = n; i >= 1; --i) sa[cnt[rk[id[i]]]--] = id[i];
              
              for(int i = 1; i <= n; i++) oldrk[i] = rk[i];
    
              for (int p = 0, i = 1; i <= n; ++i) {
                if (oldrk[sa[i]] == oldrk[sa[i - 1]] &&
                    oldrk[up[po][sa[i]]] == oldrk[up[po][sa[i - 1]]]) {
                  rk[sa[i]] = p;
                } else {
                  rk[sa[i]] = ++p;
                }
              }
            }
    
    
    
            cout << "Case #" << ++cas << ": ";
            int cur = sa[n] - 1;
            for(int i = 1; i <= n; i++) {
                cout << arr[cur + 1];
                cur = (1ll * cur * cur + 1) % n;
            }
            cout << endl;
        }
    }
    
  • 相关阅读:
    面向报文(UDP)和面向字节流(TCP)的区别
    c++ 字符串和数字拼接
    OpenGL中着色器,渲染管线,光栅化
    阅读计划
    课堂测试
    多态与异常处理
    《大道至简》第七八章读后感
    继承与接口课堂作业
    《大道至简》第六章读后感
    随机数组
  • 原文地址:https://www.cnblogs.com/limil/p/14761538.html
Copyright © 2011-2022 走看看