[BZOJ2882]工艺

Posted Elder_Giang

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了[BZOJ2882]工艺相关的知识,希望对你有一定的参考价值。

2882: 工艺

Time Limit: 10 Sec  Memory Limit: 128 MB Submit: 1085  Solved: 469 [Submit][Status][Discuss]

Description

小敏和小燕是一对好朋友。
他们正在玩一种神奇的游戏,叫Minecraft。
他们现在要做一个由方块构成的长条工艺品。但是方块现在是乱的,而且由于机器的要求,他们只能做到把这个工艺品最左边的方块放到最右边。
他们想,在仅这一个操作下,最漂亮的工艺品能多漂亮。
两个工艺品美观的比较方法是,从头开始比较,如果第i个位置上方块不一样那么谁的瑕疵度小,那么谁就更漂亮,如果一样那么继续比较第i+1个方块。如果全都一样,那么这两个工艺品就一样漂亮。

Input

第一行两个整数n,代表方块的数目。
第二行n个整数,每个整数按从左到右的顺序输出方块瑕疵度的值。

Output

一行n个整数,代表最美观工艺品从左到右瑕疵度的值。

Sample Input


10
10 9 8 7 6 5 4 3 2 1

Sample Output


1 10 9 8 7 6 5 4 3 2

HINT

这题可以通过把串复制一遍接在后面,然后SA做
#include <cstdio>
#include <algorithm>
using namespace std;
inline int readint(){
    int n = 0;
    char ch = getchar();
    while(ch < 0 || ch > 9) ch = getchar();
    while(ch <= 9 && ch >= 0){
        n = (n << 3) + (n << 1) + ch - 0;
        ch = getchar();
    }
    return n;
}
const int maxn = 300000 + 10;
int n, m;
int s[maxn * 2], num[maxn], ref[maxn];
inline bool cmp(int *arr, int x, int y, int l){
    return arr[x] == arr[y] && arr[x + l] == arr[y + l];
}
int sa[maxn * 2], rank[maxn * 2];
int tax[maxn * 2], tp[maxn * 2];
inline void Rsort(){
    for(int i = 0; i <= m; i++) tax[i] = 0;
    for(int i = 1; i <= n; i++) tax[rank[tp[i]]]++;
    for(int i = 1; i <= m; i++) tax[i] += tax[i - 1];
    for(int i = n; i; i--) sa[tax[rank[tp[i]]]--] = tp[i];
}
void suffix(){
    for(int i = 1; i <= n; i++){
        tp[i] = i;
        rank[i] = s[i];
    }
    Rsort();
    for(int w = 1, p; w < n; w <<= 1, m = p){
        p = 0;
        for(int i = n - w + 1; i <= n; i++) tp[++p] = i;
        for(int i = 1; i <= n; i++) if(sa[i] > w) tp[++p] = sa[i] - w;
        Rsort();
        swap(rank, tp);
        rank[sa[1]] = p = 1;
        for(int i = 2; i <= n; i++)
            rank[sa[i]] = cmp(tp, sa[i - 1], sa[i], w) ? p : ++p;
        if(p == n) return;
    }
}
int main(){
    n = readint();
    for(int i = 1; i <= n; i++)
        num[i] = s[i] = readint();
    sort(num + 1, num + n + 1);
    m = unique(num + 1, num + n + 1) - (num + 1);
    for(int t, i = 1; i <= n; i++){
        t = lower_bound(num + 1, num + m + 1, s[i]) - num;
        ref[t] = s[i];
        s[i] = s[i + n] = t;
    }
    n <<= 1;
    suffix();
    n >>= 1;
    int a;
    for(int i = 1; ; i++){
        if(sa[i] <= n){
            a = sa[i];
            break;
        }
    }
    for(int i = 1; i < n; i++)
        printf("%d ", ref[s[a++]]);
    printf("%d", ref[s[a]]);
    return 0;
}

 

或者SAM也可以做
但更吼的是最小表示法
#include <cstdio>
const int maxn = 300000 + 10;
int n, num[maxn];
int zx(){
    int i = 1, j = 2, k = 0;
    int nxi, nxj, t;
    while(i <= n && j <= n && k <= n){
        nxi = i + k; if(nxi > n) nxi -= n;
        nxj = j + k; if(nxj > n) nxj -= n;
        t = num[nxi] - num[nxj];
        if(t == 0) k++;
        else{
            if(t > 0) i += k + 1;
            else j += k + 1;
            if(i == j) i++;
            k = 0; 
        }
    }
    return i < j ? i : j;
}
int main(){
    scanf("%d", &n);
    for(int i = 1 ; i <= n; i++) scanf("%d", num + i);
    int a = zx();
    for(int i = 1; i < n; i++){
        printf("%d ", num[a++]);
        if(a > n) a -= n;
    }
    printf("%d", num[a]);
    return 0;
}

 

以上是关于[BZOJ2882]工艺的主要内容,如果未能解决你的问题,请参考以下文章

bzoj 2882: 工艺

[BZOJ2882]工艺

BZOJ2882工艺(后缀数组)

BZOJ2882工艺(后缀自动机)

BZOJ2882工艺 [SAM]

Bzoj2882 工艺 [西方算法]