【poj3623】 Best Cow Line, Gold

http://poj.org/problem?id=3623 (题目链接)

题意

  给出一个字符串,每次可以取首或尾接到一个新的字符串后面,求构出的字典序最小的新字符串。

Solution

  首先可以发现,一定是优先选择字典序最小的,所以就将字符串反过来接在后面并用分隔符隔开,求一遍后缀数组,然后每次比较首和尾的rank,取rank靠前的记入答案即可。

细节

  每80个字母一行→_→

代码

// poj3623
#include<algorithm>
#include<iostream>
#include<cstdlib>
#include<cstring>
#include<cstdio>
#include<cmath>
#include<ctime>
#define LL long long
#define inf 1<<30
#define Pi acos(-1.0)
#define free(a) freopen(a".in","r",stdin),freopen(a".out","w",stdout);
using namespace std;

const int maxn=300010;
int sa[maxn],height[maxn],rank[maxn],n;
char s[maxn],ch[maxn/10][20],ans[maxn];

namespace Suffix {
	int wa[maxn],wb[maxn],ww[maxn];
	bool cmp(int *r,int a,int b,int l) {
		return r[a]==r[b] && r[a+l]==r[b+l];
	}
	void da(char *r,int *sa,int n,int m) {
		int i,j,p,*x=wa,*y=wb;
		for (i=0;i<=m;i++) ww[i]=0;
		for (i=1;i<=n;i++) ww[x[i]=r[i]]++;
		for (i=1;i<=m;i++) ww[i]+=ww[i-1];
		for (i=n;i>=1;i--) sa[ww[x[i]]--]=i;
		for (p=0,j=1;p<n;j*=2,m=p) {
			for (p=0,i=n-j+1;i<=n;i++) y[++p]=i;
			for (i=1;i<=n;i++) if (sa[i]>j) y[++p]=sa[i]-j;
			for (i=0;i<=m;i++) ww[i]=0;
			for (i=1;i<=n;i++) ww[x[y[i]]]++;
			for (i=1;i<=m;i++) ww[i]+=ww[i-1];
			for (i=n;i>=1;i--) sa[ww[x[y[i]]]--]=y[i];
			for (swap(x,y),p=x[sa[1]]=1,i=2;i<=n;i++)
				x[sa[i]]=cmp(y,sa[i-1],sa[i],j) ? p : ++p;
		}
	}
	void calheight(char *r,int *sa,int n) {
		for (int i=1;i<=n;i++) rank[sa[i]]=i;
		for (int k=0,i=1;i<=n;i++) {
			if (k) k--;
			int j=sa[rank[i]-1];
			while (r[i+k]==r[j+k]) k++;
			height[rank[i]]=k;
		}
	}
}

int main() {
	scanf("%d",&n);
	char ch[10];
	for (int i=1;i<=n;i++) {
		scanf("%s",ch);s[i]=ch[0];
	}
	s[n+1]=‘#‘;
	int len=n;
	for (int i=1;i<=n;i++) s[n+i+1]=s[n-i+1];
	n=n+n+1;
	Suffix::da(s,sa,n,300);
	Suffix::calheight(s,sa,n);
	int tot=0,l=1,r=len;
	while (tot<len) {
		int x=rank[l],y=rank[len-r+1+len+1];
		if (x<y) ans[++tot]=s[l++];
		else ans[++tot]=s[r--];
	}
	for (int i=1;i<=tot;i++) {
		printf("%c",ans[i]);
		if (i%80==0) puts("");
	}
    return 0;
}
时间: 2024-10-24 17:37:42

【poj3623】 Best Cow Line, Gold的相关文章

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

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

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

【网络流】Modular Production Line

[网络流]Modular Production Line 焦作上的一道,网络流24题中的原题.... https://nanti.jisuanke.com/t/31715 给出了1e5个点,但是因为最多200条边,也就是最多用到400个点,所用先离散化,然后建图. 建图: 1.对权值为w的区间[u,v],加边id(u)->id(v+1),容量为1,费用为-w; 2.对所有相邻的点加边id(i)->id(i+1),容量为正无穷,费用为0; 3.建立源点汇点,由源点s向最左侧的点加边,容量为K,费

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]

【POJ 3617】Best Cow Line

Best Cow Line Time Limit: 1000MS   Memory Limit: 65536K Total Submissions: 13950   Accepted: 3987 Description 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