zoukankan      html  css  js  c++  java
  • POJ 3581 Sequence(后缀数组)题解

    题意:

    已知某字符串(str)满足(str_1 > max{str_2,str_3 cdots str_n}),现要求把这个字符串分成连续的三组,然后每组都翻转,问字典序最小是什么?

    思路:

    因为(str_1 > max{str_2,str_3 cdots str_n}),所以第一部分直接翻转后跑(sa)求字典序最小就行了。那么现在问题转化为:把这个字符串分成两半,然后每组都翻转,问字典序最小是什么?
    我们假设这个字符串为(s_1s_2 cdots s_n),那么可以得到分成两半反转后为(s_ks_{k-1}s_{k-2} cdots s_1s_ns_{n-1} cdots s_{k+1}),我们可以发现,这个串其实就是(s_ns_{n-1}s_{n-2} cdots s_1s_ns_{n-1} cdots s_{1})的一个子串,那么我就把这个串反向复制两遍,然后后缀数组求字典序最小即可。
    tips:多组输入必wa

    代码:

    #include<map>
    #include<set>
    #include<queue>
    #include<cmath>
    #include<stack>
    #include<ctime>
    #include<string>
    #include<vector>
    #include<cstdio>
    #include<cstring>
    #include<sstream>
    #include<iostream>
    #include<algorithm>
    using namespace std;
    typedef long long ll;
    typedef unsigned long long ull;
    const int maxn = 4e5 + 10;
    const int INF = 0x3f3f3f3f;
    const ull seed = 11;
    const int MOD = 1e9 + 7;
    using namespace std;
    
    int str[maxn];
    int t1[maxn], t2[maxn], c[maxn];
    int sa[maxn];
    int rk[maxn];
    int height[maxn];
    bool cmp(int *r, int a, int b, int l){
        return r[a] == r[b] && r[a + l] == r[b + l];
    }
    void da(int *str, int n, int m){
        n++;
        int i, j, p, *x = t1, *y = t2;
        for(i = 0; i < m; i++) c[i] = 0;
        for(i = 0; i < n; i++) c[x[i] = str[i]]++;
        for(i = 1; i < m; i++) c[i] += c[i - 1];
        for(i = n - 1; i >= 0; i--) sa[--c[x[i]]] = i;
        for(j = 1; j <= n; j <<= 1){
            p = 0;
            for(i = n - j; i < n; i++) y[p++] = i;
            for(i = 0; i < n; i++) if(sa[i] >= j) y[p++] = sa[i] - j;
            for(i = 0; i < m; i++) c[i] = 0;
            for(i = 0; i < n; i++) c[x[y[i]]]++;
            for(i = 1; i < m; i++) c[i] += c[i - 1];
            for(i = n - 1; i >= 0; i--) sa[--c[x[y[i]]]] = y[i];
            swap(x, y);
            p = 1; x[sa[0]] = 0;
            for(i = 1; i < n; i++)
                x[sa[i]] = cmp(y, sa[i - 1], sa[i], j)? p - 1 : p++;
            if(p >= n) break;
            m = p;
        }
    //    int k = 0;
    //    n--;
    //    for(i = 0; i <= n; i++) rk[sa[i]] = i;
    //    for(i = 0; i < n; i++){
    //        if(k) k--;
    //        j = sa[rk[i] - 1];
    //        while(str[i + k] == str[j + k]) k++;
    //        height[rk[i]] = k;
    //    }
    }
    vector<int> vv;
    int s[maxn];
    int ans[maxn];
    int main(){
        int n;
        int Max;
        scanf("%d", &n);
        vv.clear();
        for(int i = 1; i <= n; i++) scanf("%d", &s[i]), vv.push_back(s[i]);
        sort(vv.begin(), vv.end());
        vv.erase(unique(vv.begin(), vv.end()), vv.end());
        for(int i = 1; i <= n; i++){
            s[i] = lower_bound(vv.begin(), vv.end(), s[i]) - vv.begin() + 1;
        }
        Max = vv.size() + 2;
        //1
        int len = n - 2;
        int cnt = 0;
        for(int i = len, j = 0; i >= 1; i--, j++){
            str[j] = s[i];
        }
        str[len] = 0;
        da(str, len, Max);
        for(int i = sa[1]; i < len; i++){
            ans[cnt++] = str[i];
        }
        //2
        len = 0;
        for(int i = n; i > cnt; i--){
            str[len++] = s[i];
        }
        for(int i = n; i > cnt; i--){
            str[len++] = s[i];
        }
        str[len] = 0;
        da(str, len, Max);
        int st;
        for(int i = 1; ; i++){
            if(sa[i] < len / 2 && sa[i] != 0){
                st = sa[i];
                break;
            }
        }
        for(int i = st; cnt < n; i++){
            ans[cnt++] = str[i];
        }
        for(int i = 0; i < cnt; i++){
            printf("%d
    ", vv[ans[i] - 1]);
        }
        return 0;
    }
    
    
  • 相关阅读:
    176. Second Highest Salary
    175. Combine Two Tables
    172. Factorial Trailing Zeroes
    171. Excel Sheet Column Number
    169. Majority Element
    168. Excel Sheet Column Title
    167. Two Sum II
    160. Intersection of Two Linked Lists
    个人博客记录
    <meta>标签
  • 原文地址:https://www.cnblogs.com/KirinSB/p/11281267.html
Copyright © 2011-2022 走看看