2882: 工艺
Time Limit: 10 Sec Memory Limit: 128 MBSubmit: 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
求一串数字循环重构后能形成的的最小字典序串。
练习后缀自动机的时候从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 ? ' ' : ' '); 103 u = v->second; 104 } 105 }
@Author: YouSiki