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 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

题目大意:只能从两头取,使字典序最小

ac代码

Problem: 3623  User: kxh1995
Memory: 1364K  Time: 438MS
Language: C++  Result: Accepted
#include<stdio.h>
#include<string.h>
#include<algorithm>
#include<stdlib.h>
#include<iostream>
#define min(a,b) (a>b?b:a)
#define max(a,b) (a>b?a:b)
#define INF 0xfffffff
#define N 60060
using namespace std;
char str[N];
int sa[N],t1[N],t2[N],c[N];
int rank[N];
void build_sa(char *s,int n,int m)
{
	int i,j,p,*x=t1,*y=t2;
	for(i=0;i<m;i++)
		c[i]=0;
	for(i=0;i<n;i++)
		c[x[i]=s[i]]++;
	for(i=1;i<m;i++)
		c[i]+=c[i-1];
	for(i=n-1;i>=0;i--)
		sa[--c[x[i]]]=i;
	for(j=1;j<=n;j<<=1)
	{
		p=0;
		for(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<m;i++)
			c[i]=0;
		for(i=0;i<n;i++)
			c[x[y[i]]]++;
		for(i=1;i<m;i++)
			c[i]+=c[i-1];
		for(i=n-1;i>=0;i--)
			sa[--c[x[y[i]]]]=y[i];
	//	swap(x,y);
		int *T=x;
		x=y;
		y=T;
		p=1;
		x[sa[0]]=0;
		for(i=1;i<n;i++)
			x[sa[i]]=y[sa[i-1]]==y[sa[i]]&&y[sa[i-1]+j]==y[sa[i]+j]?p-1:p++;
		if(p>=n)
			break;
		m=p;
	}
}
int main()
{
	int n;
	while(scanf("%d",&n)!=EOF)
	{
		char s[2];
		int i;
		for(i=0;i<n;i++)
		{
			scanf("%s",s);
			str[i]=s[0];
			str[n*2-i]=s[0];
		}
		str[n]=0;
		str[2*n+1]=0;
		build_sa(str,2*n+2,200);
		for(i=0;i<2*n+2;i++)
			rank[sa[i]]=i;
		int l=0,r=n+1;
		int len=0;
		while((len++)<n)
		{
			if(rank[l]<rank[r])
			{
				printf("%c",str[l]);
				l++;
			}
			else
			{
				printf("%c",str[r]);
				r++;
			}
			//len++;
			if(len%80==0)
				printf("\n");
		}
		if(len%80)
			printf("\n");
	}
}

版权声明:本文为博主原创文章,未经博主允许不得转载。

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

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

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(模拟)

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

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

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

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

[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

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

POJ 题目2774 Long Long Message(后缀数组,求最长公共子串长度)

Long Long Message Time Limit: 4000MS   Memory Limit: 131072K Total Submissions: 23696   Accepted: 9705 Case Time Limit: 1000MS Description The little cat is majoring in physics in the capital of Byterland. A piece of sad news comes to him these days:

POJ 题目 3693 Maximum repetition substring(后缀数组+RMQ+枚举求最小字典序的重复次数最多的子串)

Maximum repetition substring Time Limit: 1000MS   Memory Limit: 65536K Total Submissions: 8067   Accepted: 2463 Description The repetition number of a string is defined as the maximum number R such that the string can be partitioned into R same conse