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 scheme this year: simply register the initial letter of every cow in the order they will appear (i.e., If FJ takes Bessie, Sylvia, and Dora in that order he just registers BSD). After the registration phase
ends, every group is judged in increasing lexicographic order according to the string of the initials of the cows‘ names.

FJ is very busy this year and has to hurry back to his farm, so he wants to be judged as early as possible. He decides to rearrange his cows, who have already lined up, before registering them.

FJ marks a location for a new line of the competing cows. He then proceeds to marshal the cows from the old line to the new one by repeatedly sending either the first or last cow in the (remainder of the) original line to the end of the new line. When he‘s
finished, FJ takes his cows for registration in this new order.

Given the initial order of his cows, determine the least lexicographic string of initials he can make this way.

Input

* Line 1: A single integer: N

* Lines 2..N+1: Line i+1 contains a single initial (‘A‘..‘Z‘) of the cow in the ith position in the original line

Output

The least lexicographic string he can make. Every line (except perhaps the last one) contains the initials of 80 cows (‘A‘..‘Z‘) in the new line.

Sample Input

6
A
C
D
B
C
B

Sample Output

ABCBCD

Source

USACO 2007 December Gold

题意:

每次只能从两边取,要求取出来之后字典序最小

思路:

求出rank数组之后再从左右开始,哪个小取哪个

#include <iostream>
#include <stdio.h>
#include <string.h>
#include <stack>
#include <queue>
#include <map>
#include <set>
#include <vector>
#include <math.h>
#include <bitset>
#include <algorithm>
#include <climits>
using namespace std;

#define LS 2*i
#define RS 2*i+1
#define UP(i,x,y) for(i=x;i<=y;i++)
#define DOWN(i,x,y) for(i=x;i>=y;i--)
#define MEM(a,x) memset(a,x,sizeof(a))
#define W(a) while(a)
#define gcd(a,b) __gcd(a,b)
#define LL long long
#define N 2000005
#define MOD 1000000007
#define INF 0x3f3f3f3f
#define EXP 1e-8
int wa[N],wb[N],wsf[N],wv[N],sa[N];
int rank[N],height[N],s[N];
//sa:字典序中排第i位的起始位置在str中第sa[i]
//rank:就是str第i个位置的后缀是在字典序排第几
//height:字典序排i和i-1的后缀的最长公共前缀
int cmp(int *r,int a,int b,int k)
{
    return r[a]==r[b]&&r[a+k]==r[b+k];
}
void getsa(int *r,int *sa,int n,int m)//n要包含末尾添加的0
{
    int i,j,p,*x=wa,*y=wb,*t;
    for(i=0; i<m; i++)  wsf[i]=0;
    for(i=0; i<n; i++)  wsf[x[i]=r[i]]++;
    for(i=1; i<m; i++)  wsf[i]+=wsf[i-1];
    for(i=n-1; i>=0; i--)  sa[--wsf[x[i]]]=i;
    p=1;
    j=1;
    for(; p<n; j*=2,m=p)
    {
        for(p=0,i=n-j; i<n; i++)  y[p++]=i;
        for(i=0; i<n; i++)  if(sa[i]>=j)  y[p++]=sa[i]-j;
        for(i=0; i<n; i++)  wv[i]=x[y[i]];
        for(i=0; i<m; i++)  wsf[i]=0;
        for(i=0; i<n; i++)  wsf[wv[i]]++;
        for(i=1; i<m; i++)  wsf[i]+=wsf[i-1];
        for(i=n-1; i>=0; i--)  sa[--wsf[wv[i]]]=y[i];
        t=x;
        x=y;
        y=t;
        x[sa[0]]=0;
        for(p=1,i=1; i<n; i++)
            x[sa[i]]=cmp(y,sa[i-1],sa[i],j)? p-1:p++;
    }
}
void getheight(int *r,int n)//n不保存最后的0
{
    int i,j,k=0;
    for(i=1; i<=n; i++)  rank[sa[i]]=i;
    for(i=0; i<n; i++)
    {
        if(k)
            k--;
        else
            k=0;
        j=sa[rank[i]-1];
        while(r[i+k]==r[j+k])
            k++;
        height[rank[i]]=k;
    }
}
char str[10];
int main()
{
    int n,i,j,k;
    while(~scanf("%d",&n))
    {
        int len = 0;
        for(i = 0; i<n; i++)
        {
            scanf("%s",str);
            s[i] = str[0];
            s[2*n-i] = str[0];
        }
        s[n] = 0;
        s[2*n+2] = 0;
        getsa(s,sa,2*n+2,200);
        for(i = 0; i<2*n+2; i++)
            rank[sa[i]] = i;
        int l = 0,r = n+1;
        while((len++)<n)
        {
            if(rank[l]<rank[r])
            {
                printf("%c",s[l]);
                l++;
            }
            else
            {
                printf("%c",s[r]);
                r++;
            }
            if(len%80==0)
                printf("\n");
        }
        if(len%80)
            printf("\n");
    }

    return 0;
}
时间: 2024-08-01 22:47:18

POJ3623:Best Cow Line, Gold(后缀数组)的相关文章

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

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

poj3623 Best Cow Line, Gold(贪心)

题目链接: huangjing 思路: 选取字典序最小的串,那么值得考虑的是当两端出现相等时,继续比较,直到出现不同的结果.. 题目: Best Cow Line, Gold Time Limit: 5000MS   Memory Limit: 65536K Total Submissions: 4574   Accepted: 1682 Description FJ is about to take his N (1 ≤ N ≤ 30,000) cows to the annual"Farme

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

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

POJ 题目3623 Best Cow Line, Gold(后缀数组rank简单应用)

Best Cow Line, Gold Time Limit: 5000MS   Memory Limit: 65536K Total Submissions: 5063   Accepted: 1806 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 arrang

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]

贪心 洛谷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

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