BZOJ 2882: 工艺

2882: 工艺

Time Limit: 10 Sec  Memory Limit: 128 MB
Submit: 599  Solved: 268
[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



【数据规模与约定】

对于20%的数据,n<=1000

对于40%的数据,n<=10000

对于100%的数据,n<=300000

Source

[Submit][Status][Discuss]

 

求一串数字循环重构后能形成的的最小字典序串。

练习后缀自动机的时候从PoPoQQQ前辈那里看到了这道题,虽然貌似用最小表示法做更合适,但是后缀自动机也可以切。

因为最终不一定(几乎是肯定不会)从一开始给出时的第一个字符开始,为了方便地处理循环问题,我们先将这个串加倍,准确地讲是把1...n-1连接到原串的后面。这样,这个加倍后的串中任意一段长度为n的子串,都是原串的一个合法的循环重构串,我们只需要找到最小的一个长度为n的子串即可,那就后缀自动机喽。

 

  1 #include <bits/stdc++.h>
  2 
  3 using namespace std;
  4 
  5 const int maxn = 6e5 + 5;
  6 
  7 #define it map<int, node*>::iterator
  8 
  9 /* MYSCANNER */
 10 
 11 const int siz = 1024;
 12 
 13 inline int get_c(void)
 14 {
 15     static char buf[siz];
 16     static char *head = buf + siz;
 17     static char *tail = buf + siz;
 18 
 19     if (head == tail)
 20         fread(head = buf, 1, siz, stdin);
 21     
 22     return *head++;
 23 }
 24 
 25 inline int get_i(void)
 26 {
 27     register int ret = 0;
 28     register int neg = false;
 29     register int bit = get_c();
 30 
 31     for (; bit < 48; bit = get_c())
 32         if (bit == '-')neg ^= true;
 33 
 34     for (; bit > 47; bit = get_c())
 35         ret = ret*10 + bit - '0';
 36 
 37     return neg ? -ret : ret;
 38 }
 39 
 40 /* AUTOMATON */
 41 
 42 struct node
 43 {
 44     int step;
 45     node *fail;
 46     map<int, node*> next;
 47     node(void)
 48     {
 49         step = 0;
 50         fail = NULL;
 51         next.clear();
 52     }
 53 }*root, *last;
 54 
 55 inline void build(void)
 56 {
 57     root = last = new node;
 58 }
 59 
 60 inline void extend(int c)
 61 {
 62     node *p = last;
 63     node *t = new node;
 64     t->step = p->step + 1;
 65     while (p && !p->next[c])
 66         p->next[c] = t, p = p->fail;
 67     if (p)
 68     {
 69         node *q = p->next[c];
 70         if (q->step == p->step + 1)
 71             t->fail = q;
 72         else
 73         {
 74             node *k = new node;
 75             k->fail = q->fail;
 76             k->next = q->next;
 77             k->step = p->step + 1;
 78             q->fail = t->fail = k;
 79             while (p && p->next[c] == q)
 80                 p->next[c] = k, p = p->fail;
 81         }
 82     }
 83     else
 84         t->fail = root;
 85     last = t;
 86 }
 87 
 88 /* MAIN FUNC */
 89 
 90 signed main(void)
 91 {
 92     build();
 93     int n = get_i();
 94     int *s = new int[n + 5];
 95     for (int i = 1; i <= n; ++i)
 96         s[i] = get_i(), extend(s[i]);
 97     for (int i = 1; i < n; ++i)extend(s[i]);
 98     for (node *u = root; n--; )
 99     {
100         it v = u->next.begin();
101         printf("%d", v->first);
102         putchar(n ? ' ' : '\n');
103         u = v->second;
104     }
105 }

 

@Author: YouSiki

posted @ 2016-12-22 20:34  YouSiki  阅读(315)  评论(0编辑  收藏  举报