字典序最小问题(POJ3617)

题目大意:给定长度为N的字符串S,要构造一个长度为N的字符串T。起初,T是一个空串,随后反复进行下列任意操作。
从S的头部删除一个字符,加到T的尾部
从S的尾部删除一个字符,加到T的尾部
目标是构造字典序尽可能小的字符串。

输入:
6
ACDBCB
输出
ABCBCD

解题思路:
这道题我们很容易想到,不断取开头或者结尾最小的一个字母放到T中就可以了。这个思路是正确的,不过我们要针对开头和结尾相同的情况来进行一下判断,便得到如下算法:
1.按照字典序比较S和将S反转后的字符串
2.如果S较小,就从S的开头取出一个字符
3.如果S’较小,就从S的末尾取出一个字符

AC代码:

#include<bits/stdc++.h>
#include<iostream>
#include<cstdio>
using namespace std;
const int N = 1e5+10;
char s[N+1];
int n;
void solve()
{
	int a = 0;
	int b = n-1;
	while(a <= b)
	{
		int left = false;
		for(int i = 0 ; a+i <= b ;  i++)
		{
			if(s[a+i]<s[b-i])
			{
				left = true;
				break;
			}
			else if(s[a+i]>s[b-i])
			{
				left = false;
				break;
			}
		}
		if(left)
		  putchar(s[a++]);
		else
		  putchar(s[b--]);
	}
	putchar('\n');
}
int main()
{
	cin >> n;
	scanf("%s",s);
	solve();
	return 0;
 } 

所以说,字典序比较类的问题,经常能用的到贪心算法。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值