POJ3617:Best Cow Line (贪心&&后缀数组)

FJ is about to take his N (1 ≤ N ≤ 2,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

----------------因为准备金马赛,所以一直在看书和博客(希望能赢一把)。之前节奏太快了,应该多思考巩固,所以减少了写代码的时间---------------

题意:给定一个字符串S,现在把这个S变成一个字符串T:每次从S的头或尾取一个字符添加到T里,要求其字典序最小。

思路:显然是贪心求解,如果S头不等于S尾,那么取小的一边加到T里。

但是如果相同,不能任取,如BCAB,如果任取B,可能变成了BABC或者BBAC,后者显然不合标准。

应该一直比较,知道不相同或者全部都相同:不相同就取小的那一边,全部相同就随意取。

比较的过程可以暴力,也可以后缀数组。

普通贪心代码:

#include<cstdio>
#include<cstdlib>
#include<iostream>
#include<algorithm>
using namespace std;
const int maxn=2010;
char c[maxn];
bool Left(int L,int R){
    while(L<=R){
        if(c[L]!=c[R])
           return c[L]<c[R];
        L++; R--;
    }
    return true;
}
int main()
{
    int N,cnt;
    scanf("%d",&N);
    for(int i=1;i<=N;i++) cin>>c[i];
    int L=1,R=N; cnt=0;
    while(L<=R){
        if(Left(L,R)) cout<<c[L++];
        else cout<<c[R--];
        cnt++;
        if(cnt==80) printf("\n"),cnt=0;
    }
    return 0;
}

后缀数组代码:

#include<cmath>
#include<math.h>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<iostream>
#include<algorithm>
using namespace std;
const int maxn=4010;
int N;char c[maxn];
struct SA
{
    int Rank[maxn],A[maxn],B[maxn],cntA[maxn],cntB[maxn],sa[maxn],tsa[maxn],ht[maxn],Min[maxn][22];
    void sort(){
       for(int i=0;i<=128;i++) cntA[i]=0;
       for(int i=1;i<=N;i++) cntA[c[i]]++;
       for(int i=1;i<=128;i++) cntA[i]+=cntA[i-1];
       for(int i=N;i>=1;i--) sa[cntA[c[i]]--]=i;
       Rank[sa[1]]=1;
       for(int i=2;i<=N;i++) Rank[sa[i]]=Rank[sa[i-1]]+(c[sa[i]]==c[sa[i-1]]?0:1);
       for(int l=1;Rank[sa[N]]<N;l<<=1){
              for(int i=0;i<=N;i++) cntA[i]=cntB[i]=0;
              for(int i=1;i<=N;i++) cntA[A[i]=Rank[i]]++;
              for(int i=1;i<=N;i++) cntB[B[i]=i+l<=N?Rank[i+l]:0]++;
              for(int i=1;i<=N;i++) cntA[i]+=cntA[i-1],cntB[i]+=cntB[i-1];
              for(int i=N;i>=1;i--) tsa[cntB[B[i]]--]=i;
              for(int i=N;i>=1;i--) sa[cntA[A[tsa[i]]]--]=tsa[i];
              Rank[sa[1]]=1;
              for(int i=2;i<=N;i++) Rank[sa[i]]=Rank[sa[i-1]]+(A[sa[i]]==A[sa[i-1]]&&B[sa[i]]==B[sa[i-1]]?0:1);
       }
    }
}S;
int main()
{
    int n,cnt;
    scanf("%d",&n);    N=n+n+1;
    for(int i=1;i<=n;i++) cin>>c[i];
    for(int i=n;i>=1;i--) c[N-i]=c[i];
    int L=1,R=n; cnt=0; S.sort();
    while(L<=R){
        if(S.Rank[L]<=S.Rank[N-R]) cout<<c[L++];
        else cout<<c[R--];
        cnt++;
        if(cnt==80) printf("\n"),cnt=0;
    }
    return 0;
}

原文地址:https://www.cnblogs.com/hua-dong/p/8810069.html

时间: 2024-10-09 19:03:27

POJ3617:Best Cow Line (贪心&&后缀数组)的相关文章

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

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

POJ3617 Best Cow Line 贪心

这题虽然简单但是挺不错的,因为过程很好,比较开发思维 和鼓励人,不像有些贪心太偏不好推反而让人厌烦 给出长度为N的字符串S,然后还有一个空串STR,每次有两个选择 1:删除S的头元素假加入STR中      2:删除S的尾元素加入STR中 是的STR字典序最小 并输出 开始可能没有什么顾虑的去想 每次比较S的头和尾元素 取小的那个删除并假如STR中,但是若S的头和尾元素一样的话这个方法就不行了,因为先取头或者尾还得看他们之间的元素,这时候是倒着来还是顺着好呢?那就直接拿顺的跟倒的进行字典序的大小

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(后缀数组)

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

题意: 给N个字符,每次只能取第一个或者最后一个,问构成最小字典序的串是什么. 思路: 贪心,每次取字典序最小的串,的首字符. 其实就是l和r比较一下构成的串那个字典序小. 这里运用后缀数组要实现O(1)的查询. 将原串反拼进串内做da. 然后根据ra判断. 代码: #include"cstdlib" #include"cstdio" #include"cstring" #include"cmath" #include&quo

BZOJ 1692 队列变换 贪心+后缀数组

题目大意:给定一个字符串,每次取头或者尾放在新字符串里,求字典序最小的新字符串 首先如果两边的字符不一样 那么肯定要选择小的放在新字符串里 但如果两边一样 比如CCBACC 肯定从尾取比较优 原因是CCA比CCB要小 于是我们把原串反写接在后面变成[email protected] 然后跑一遍后缀数组 每次就能O(1)比较两个子串的大小了 时间复杂度O(nlogn) #include<cstdio> #include<cstring> #include<iostream>

poj3617 Best Cow Line(贪心,字典序问题)

https://vjudge.net/problem/POJ-3617 这类字符串处理字典序问题经常用到贪心, 每决定输出一个字符之前,都要前后i++,j--逐个比大小,直至比出为止. 1 #include<iostream> 2 #include<cstdio> 3 #include<queue> 4 #include<cstring> 5 #include<algorithm> 6 #include<cmath> 7 #inclu

POJ 3617 Best Cow Line (贪心)

题意: 给定长度为N的字符串S,要构造一个长度为N的字符串T.起初T是一个空串,随后反复进行下列任意操作 1.从字符串S头部删除一个字符,加到T的尾部 2.从字符串S尾部删除一个字符,加到T的尾部 目的是,构造字典序尽可能小的字符串T 思路:简单贪心,比较当前字符串S首尾字符的大小,选取小的加入T,若两者相同,则比较下一个字符. #include<stdio.h> #include<queue> #include<iostream> #include<algori

POJ3617 Best Cow Line 馋

虽然这个问题很简单,但非常好,由于过程是很不错的.发展思路的比较 并鼓励人们,不像有些贪心太偏,推动穷人,但恼人 鉴于长N弦S,然后又空字符串STR.每当有两个选择 1:删S增加虚假的第一要素STR于      2:删S增加最后一个元素STR于 是的STR字典序最小 并输出 開始可能没有什么顾虑的去想 每次比較S的头和尾元素 取小的那个删除并假如STR中.可是若S的头和尾元素一样的话这种方法就不行了,由于先取头或者尾还得看他们之间的元素,这时候是倒着来还是顺着好呢?那就直接拿顺的跟倒的进行字典序