[luoguP2870] [USACO07DEC]最佳牛线,黄金Best Cow Line, Gold(后缀数组)

传送门

数据小的话贪心就行。

可以把这个串翻转再接到后面,再求后缀数组,求出 rank 数组就很简单了。

——代码

 1 #include <cstdio>
 2 #include <iostream>
 3 #define N 60001
 4
 5 int n, len, m = 256, sum;
 6 int buc[N], x[N], y[N], sa[N], rank[N];
 7 char s[N];
 8
 9 inline void build_sa()
10 {
11     int i, k, p;
12     for(i = 0; i < m; i++) buc[i] = 0;
13     for(i = 0; i < len; i++) buc[x[i] = s[i]]++;
14     for(i = 1; i < m; i++) buc[i] += buc[i - 1];
15     for(i = len - 1; i >= 0; i--) sa[--buc[x[i]]] = i;
16     for(k = 1; k <= len; k <<= 1)
17     {
18         p = 0;
19         for(i = len - 1; i >= len - k; i--) y[p++] = i;
20         for(i = 0; i < len; i++) if(sa[i] >= k) y[p++] = sa[i] - k;
21         for(i = 0; i < m; i++) buc[i] = 0;
22         for(i = 0; i < len; i++) buc[x[y[i]]]++;
23         for(i = 1; i < m; i++) buc[i] += buc[i - 1];
24         for(i = len - 1; i >= 0; i--) sa[--buc[x[y[i]]]] = y[i];
25         std::swap(x, y);
26         p = 1, x[sa[0]] = 0;
27         for(i = 1; i < len; i++)
28             x[sa[i]] = y[sa[i - 1]] == y[sa[i]] && y[sa[i - 1] + k] == y[sa[i] + k] ? p - 1 : p++;
29         if(p >= len) break;
30         m = p;
31     }
32 }
33
34 int main()
35 {
36     int i, l, r;
37     scanf("%d", &n);
38     len = n * 2;
39     for(i = 0; i < n; i++) getchar(), s[i] = getchar(), s[len - i - 1] = s[i];
40     build_sa();
41     for(i = 0; i < len; i++) rank[sa[i]] = i;
42     l = 0, r = n - 1;
43     while(l <= r)
44     {
45         if(rank[l] <= rank[len - r - 1]) putchar(s[l++]);
46         else putchar(s[r--]);
47         if(++sum == 80) sum = 0, putchar(‘\n‘);
48     }
49     return 0;
50 }

时间: 2024-11-10 07:51:34

[luoguP2870] [USACO07DEC]最佳牛线,黄金Best Cow Line, Gold(后缀数组)的相关文章

POJ3623:Best Cow Line, Gold(后缀数组)

Description FJ is about to take his N (1 ≤ N ≤ 30,000) cows to the annual"Farmer of the Year" competition. In this contest every farmer arranges his cows in a line and herds them past the judges. The contest organizers adopted a new registration

poj 3623 Best Cow Line, Gold 后缀数组 + 贪心

题目链接 题目描述 对于一个给定的字符串,可以从左右两端取字符,依次排列构成一个新的字符串. 求可能构成的字符串中字典序 最小的一个. 例:ACDBCB -> ABCBCD 思路 参考自 xueyifan1993. 正确的 贪心 姿势: 记左端位置为 \(l\),右端位置为 \(r\),比较 \(suffix(l)\) 与 \(inv(prefix(r))\),取小者. 比较 则显然是借助 \(rank\) 数组. // 以及正确的I/O姿势真的重要... // scanf+printf:117

贪心 洛谷P2870 [USACO07DEC]最佳牛线,黄金Best Cow Line, Gold

[USACO07DEC]最佳牛线,黄金Best Cow Line, Gold 题目描述 FJ is about to take his N (1 ≤ N ≤ 30,000) cows to the annual"Farmer of the Year" competition. In this contest every farmer arranges his cows in a line and herds them past the judges. The contest organ

P2870 [USACO07DEC]最佳牛线,黄金Best Cow Line, Gold 解题报告

P2870 [USACO07DEC]最佳牛线,黄金Best Cow Line, Gold 题意 给一个字符串,每次可以从两边中的一边取一个字符,要求取出的字符串字典序最小 可以Hash+二分 也可以SA 首先贪心选字典序小的 然后遇到相等的了比Rank数组,把原串倍长一下就可以比了. Code: #include <cstdio> #include <algorithm> const int N=6e4+10; char s[N],ans[N]; int sa[N],Rank[N]

[Luogu2870] [USACO07DEC]最佳牛线Best Cow Line(贪心+后缀数组)

[Luogu2870] [USACO07DEC]最佳牛线Best Cow Line(贪心+后缀数组) 题面 FJ打算带他的\(N(1 \leq N \leq 30,000)\)头奶牛去参加一年一度的"全美农场主大奖赛".在这场比赛中,每个参赛者都必须让他的奶牛排成一列,然后领她们从裁判席前依次走过. 今年,竞赛委员会在接受队伍报名时,采用了一种新的登记规则:他们把所有队伍中奶牛名字的首字母取出,按它们对应奶牛在队伍中的次序排成一列(比如说,如果FJ带去的奶牛依次为Bessie.Sylv

P2870 [USACO07DEC]最佳牛线,黄金Best Cow Line, Gold

题目描述 FJ is about to take his N (1 ≤ N ≤ 30,000) cows to the annual"Farmer of the Year" competition. In this contest every farmer arranges his cows in a line and herds them past the judges. The contest organizers adopted a new registration scheme

POJ 3623 Best Cow Line, Gold(模拟)

题意  给你一个字符序列   你每次可以从它的头部或尾部拿出一个字符组成一个新的字符序列   输出这样做能达到的最小的字符序列   每行最多输出80个字符(开始被这个坑了好久) 直接模拟就行  哪边小就选哪边  相等就往内看 #include<cstdio> #include<iostream> #include<string> using namespace std; const int N = 30010; int main() { char s[N][2]; in

HDU 3623 Best Cow Line, Gold(模拟,注意思路,简单)

题目 POJ 3617 和 这道题题目一样,只是范围稍稍再小一点. //模拟试试 #include<stdio.h> #include<string.h> #include<algorithm> using namespace std; char s[30010][2]; bool bijiao(int st,int ed) { if(st==ed) return true; if(s[st][0]<s[ed][0]) return true; else if(s

POJ 3623 Best Cow Line, Gold(字符串处理)

题意:给你一个字符串,让你重新排列,只能从头或者尾部取出一个放到新字符串队列的最后.按照字典序. 解决方法:比较前后两个的大小,谁小输出谁,相等,就往当中比来确定当前应该拿最前面的还是最后面的,如果再相等就继续.... 所以比较这个动作的单一功能,可以写成一个check函数,方便操作也方便递归. #include<iostream> #include<cstring> using namespace std; #define MAX 30005 char str[MAX]; int