题目描述
密码学是研究编制密码和破译密码的技术科学。研究密码变化的客观规律,应用于编制密码以保守通信秘密的,称为编码学;应用于破译密码以获取通信情报的,称为破译学,总称密码学。密码是通信双方按约定的法则进行信息特殊变换的一种重要保密手段。依照这些法则,变明文为密文,称为加密变换;变密文为明文,称为脱密变换。密码在早期仅对文字或数码进行加、脱密变换,随着通信技术的发展,对语音、图像、数据等都可实施加、脱密变换。
现在要求你用下面给定的方法对数据实现加密。给定长度为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
样例输入
6
ACDBCB
样例输出
ABCBCD
解题思路:
假想存在两个指针,一个总是指向第一个字符,一个指向最后一个字符。要想字典序最小,只需每次都在首尾之间选一个最小的字符,最理想的情况是正好不相等,则直接选走加到新的串上,并将原字符串中的字符删除(方便下一轮指针仍从首尾走)。当遇到相等字符时,则需要一直向后移动首指针和向前移动尾指针,直到两字符不相等或首指针到了尾指针后,及时保存此时的两指针所指向字符字典序较小的那一端,下轮循环就从这一端开始。当原字符串删除完后,新字符串中的即为待求值。
java代码:
import java.util.Scanner;
public class Main {
public static void main(String[] args) {
Scanner scan = new Scanner(System.in);
scan.nextInt();
String s = scan.next();
scan.close();
StringBuilder b = new StringBuilder(s);
StringBuilder c = new StringBuilder();
String flag = "null";
while(b.length() != 0) {
int i = 0;
int j = b.length() - 1;
if(flag.equals("l")) {
c.append(b.charAt(i));
b.deleteCharAt(i);
flag = "null";
continue;
}else if(flag.equals("r")) {
c.append(b.charAt(j));
b.deleteCharAt(j);
flag = "null";
continue;
}
if(b.charAt(i) != b.charAt(j)) {
if(b.charAt(i) < b.charAt(j)) {
c.append(b.charAt(i));
b.deleteCharAt(i);
}else {
c.append(b.charAt(j));
b.deleteCharAt(j);
}
}else {
while(b.charAt(i) == b.charAt(j) && i < j) {
i++;
j--;
}
if(b.charAt(i) < b.charAt(j)) {
flag = "l";
}else {
flag = "r";
}
}
}
System.out.println(c.toString());
}
}