[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也可以做,但由于字符集大小是$O(n)$的,所以时间复杂度为$O(nlogn)$
然后就TLE了
#include <map> #include <cstdio> 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; struct State{ int link, len; map<int, int> son; }st[maxn * 4]; int sam_cnt, last; void sam_init(){ sam_cnt = last = 0; st[0].len = 0; st[0].link = -1; st[0].son.clear(); } inline void sam_extend(int idx){ int cur = ++sam_cnt; st[cur].len = st[last].len + 1; st[cur].son.clear(); int p; for(p = last; p != -1 && !st[p].son.count(idx); p = st[p].link) st[p].son[idx] = cur; if(p == -1) st[cur].link = 0; else{ int q = st[p].son[idx]; if(st[p].len + 1 == st[q].link) st[cur].link = q; else{ int clone = ++sam_cnt; st[clone].len = st[p].len + 1; st[clone].son = st[q].son; st[clone].link = st[q].link; for(; p != -1 && st[p].son[idx] == q; p = st[p].link) st[p].son[idx] = clone; st[cur].link = st[q].link = clone; } } last = cur; } int n, num[maxn]; int main(){ n = readint(); sam_init(); for(int i = 1; i <= n; i++) sam_extend(num[i] = readint()); for(int i = 1; i <= n; i++) sam_extend(num[i]); int p = 0; map<int, int>::iterator it; for(int i = 1; i < n; i++){ it = st[p].son.begin(); printf("%d ", it -> first); p = it -> second; } printf("%d", st[p].son.begin() -> first); return 0; }
坠吼的是最小表示法
#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; }