* 题目描述
有一种技巧可以对数据进行加密,它使用一个单词作为它的密匙。下面是它的工作原理:
首先,选择一个单词作为密匙,如TRAILBLAZERS。如果单词中包含有重复的字母,只保留第1个,其余几个丢弃。现在,修改过的那个单词属于字母表的下面,如下所示:
A B C D E F G H I J K L M N O P Q R S T U V W X Y Z
T R A I L B Z E S C D F G H J K M N O P Q U V W X Y
上面其他用字母表中剩余的字母填充完整。在对信息进行加密时,信息中的每个字母被固定于顶上那行,并用下面那行的对应字母一一取代原文的字母(字母字符的大小写状态应该保留)。因此,使用这个密匙,Attack AT DAWN(黎明时攻击)就会被加密为Tpptad TP ITVH。
请实现下述接口,通过指定的密匙和明文得到密文。
详细描述:
接口说明
原型:
voidencrypt(char * key,char * data,char * encrypt);
输入参数:
char * key:密匙
char * data:明文
输出参数:
char * encrypt:密文
返回值:
void
输入描述:
先输入key和要加密的字符串
输出描述:
返回加密后的字符串
输入例子:
nihao
ni
输出例子:
有一种技巧可以对数据进行加密,它使用一个单词作为它的密匙。下面是它的工作原理:
首先,选择一个单词作为密匙,如TRAILBLAZERS。如果单词中包含有重复的字母,只保留第1个,其余几个丢弃。现在,修改过的那个单词属于字母表的下面,如下所示:
A B C D E F G H I J K L M N O P Q R S T U V W X Y Z
T R A I L B Z E S C D F G H J K M N O P Q U V W X Y
上面其他用字母表中剩余的字母填充完整。在对信息进行加密时,信息中的每个字母被固定于顶上那行,并用下面那行的对应字母一一取代原文的字母(字母字符的大小写状态应该保留)。因此,使用这个密匙,Attack AT DAWN(黎明时攻击)就会被加密为Tpptad TP ITVH。
请实现下述接口,通过指定的密匙和明文得到密文。
详细描述:
接口说明
原型:
voidencrypt(char * key,char * data,char * encrypt);
输入参数:
char * key:密匙
char * data:明文
输出参数:
char * encrypt:密文
返回值:
void
输入描述:
先输入key和要加密的字符串
输出描述:
返回加密后的字符串
输入例子:
nihao
ni
输出例子:
le
import java.util.*;
public class NC_036_字符串加密 {
public static HashMap<Character,Character> hm;//声明一个HashMap,用来存储原始26个字符和加密处理后对应的新的26个字符
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
while(sc.hasNext()){
String secretKey = sc.next();//秘钥
String express = sc.next();//明文
if(secretKey == null || secretKey.length() == 0){
return;
}
secretKey = secretKey.toLowerCase();//将输入的秘钥全部转换为小写字符
//处理秘钥--将秘钥中重复的字符给去掉
String noRepeatKey = deleteRepeatChar(secretKey);
char[] abc = new char[26];//用于存放26个英文小写字符
for(int j=0; j < abc.length; j++){
abc[j] = (char)('a' + j);
}
char[] noReKey = noRepeatKey.toCharArray();//将去掉重复字符的秘钥存储为为字符数组形式
//声明一个k-v哈希Map的键值对形式,用来存储字符加密后的字符集
hm = new HashMap<Character,Character>();
int i;
for(i=0; i<noReKey.length; i++){
hm.put(abc[i], noReKey[i]);//abc[i]为原来的26个字符顺序,noReKey[i]为去掉重复字符的秘钥
}
for(int k=0; k<abc.length; k++){
if(!hm.containsValue(abc[k])){
hm.put(abc[i], abc[k]);//将键值对中剩余的值补全
i++;
}else{
continue;
}
}
//测试用的代码:打印hm中的信息(遍历HashMap的方法)
// Iterator iter = hm.entrySet().iterator();
// while (iter.hasNext()) {
// Map.Entry entry = (Map.Entry) iter.next();
// Character key = (Character) entry.getKey();
// Character val = (Character) entry.getValue();
// System.out.println("key键---值: "+ key + "," + val);
// }
//用明文去k-v中查找密文,进行加密后编码
String strInfo = secretInfo(express, hm);
System.out.println(strInfo);
}
}
/**
* @param str 需要加密的内容
* @param hm 密文对应的HashMap
* @return 返回加密后的内容
*/
public static String secretInfo(String str, HashMap<Character,Character> hm){
StringBuilder sb = new StringBuilder();
for(int i = 0; i < str.length(); i++){
char ch1 = str.charAt(i);
char ch2 = ch1;
if(ch1>='a' && ch1<='z'){//明文中出现的小写字符添加到字符串sb中
sb.append(hm.get(ch1));
}else if(ch1>='A' && ch1<='Z'){//明文中的大写字符先变成小写,找到K-V中的值,在将得到的值变成大写添加到字符串sb中
ch1 = Character.toLowerCase(ch1);
ch2 = hm.get(ch1);
ch2 = Character.toLowerCase(ch2);
sb.append(ch2);
}else{//明文中的其他字符,例如:空格等
sb.append(ch1);
}
}
return sb.toString();
}
/**
* @param str 需要删除秘钥中重复的字符串
* @return 删除重复字符后的秘钥
*/
public static String deleteRepeatChar(String str){
TreeSet<Character> noRepeat = new TreeSet<Character>();
ArrayList<Character> list = new ArrayList<Character>();
for(int i = 0; i < str.length(); i++){
noRepeat.add(str.charAt(i));//noRepeat是用来确保集合中字符的唯一性
}
for(int i = 0; i < str.length(); i++){
if(noRepeat.contains(str.charAt(i)) && (!list.contains(str.charAt(i)))){
list.add(str.charAt(i));//是list是用来确保字符出现的顺序性
}else{
continue;
}
}
str = "";
for(Character index : list){//遍历list,将字符添加到字符串str中
str += index;
}
return str;
}
}