算法导论3 A 数据加密(贪心)

题目:

题目描述

密码学是研究编制密码和破译密码的技术科学。研究密码变化的客观规律,应用于编制密码以保守通信秘密的,称为编码学;应用于破译密码以获取通信情报的,称为破译学,总称密码学。密码是通信双方按约定的法则进行信息特殊变换的一种重要保密手段。依照这些法则,变明文为密文,称为加密变换;变密文为明文,称为脱密变换。密码在早期仅对文字或数码进行加、脱密变换,随着通信技术的发展,对语音、图像、数据等都可实施加、脱密变换。
现在要求你用下面给定的方法对数据实现加密。给定长度为n的字符串S(1<=n<=2000,S中只有大写字母)作为明文,要求构造一个字符串T作为密文,起初T是一个空串,之后反复执行以下任意操作
1.从S的头部删除一个字符,加入到T的尾部
2.从S的尾部删除一个字符,加入到T的尾部
最后S会变成空串,T会变成一个长度为n的字符串作为密文。当然并非所有的构造方案都是符合条件的,我们要求构造出的密文T的字典序尽可能小,你能找出这个字典序最小的密文吗?

输入

输入包含多组数据,每组数据占两行,第一行为一个整数n(1<=n<=2000)代表字符串S的长度,第二行为一个长度为n的字符串S代表明文,保证S中只有大写字母

输出

对每组数据,输出一行字符串,代表构造出的字典序最小的密文T

样例输入 Copy

6

ACDBCB

样例输出 Copy

ABCBCD

解析:

一开始用dfs做,时间超限。剪枝之后发现还是时间超限,意识到这道题肯定不是用dfs做的,上网一看果然别人都是用的贪心。

对于这一题的贪心思想:

如果左右两头的字母不一样,取字母序小的。

如果一样,就比较双方里面的那一位,如果还一样,就再向里比较一位,直到找出比较小的,就用小的那边的,如果直到找完了还都一样,那么取哪边都无所谓了。

代码:

#include<iostream>
using namespace std;
int main()
{
	int n;
	string s;
	while(cin>>n>>s)
	{
		int left = 0,right = n-1;
		string ans = "";
		while(left!=right)
		{
			if(s[left]<s[right])
			{
				ans = ans+s[left++];
			}
			else if(s[left]>s[right])
			{
				ans = ans+s[right--];
			}
			else
			{
				int l = left + 1;
				int r = right -1;
				while(s[l]==s[r]&&l<r)
				{
					l++;
					r--;
				}
				if(l>=r)//说明一直到最后都是一样的
				{
					ans = ans+s[left++];
				} 
				else if(s[l]<s[r])
				{
					ans = ans+s[left++];
				}
				else
				{
					ans = ans+s[right--];
				}
			}
		}
		ans = ans + s[left];
		cout<<ans<<'\n';
	}
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

owooooow

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值