加密解密

标题:加密解密


    Playfair密码由英国人发明,它使用方便而且可以让频度分析法失效,直到一战中才被破译。
    其一变种方法如下:首先选择一个密钥单词(称为pair)(剔除重复字母,且都为小写字母),然后与字母表中其他字母一起填入至一个5x5的方阵中,填入方法如下:
1.首先按行填入密钥串,重复的字母忽略之。
2.紧接其后,按字母序按行填入不在密钥串中的字母。
3.由于方阵中只有25个位置,最后剩下的那个字母则不需填入。
如果密钥为lanqiao,则该方阵如下:  
l a n q i
o b c d e
f g h j k
m p r s t
u v w x y


在加密一对字母时,如da,在方阵中找到以这两个字母为顶点的矩形。
这对字母的加密字母为该矩形的另一对顶点,如本例中为bq。


请设计程序,使用上述方法对输入串进行加密,并输出加密后的串。


另有细则如下:
1、一对一对取字母,如果最后只剩下一个字母,则不变换,直接放入加密串中;
2、如果一对字母中的两个字母相同,则不变换,直接放入加密串中;
3、如果一对字母中有一个字母不在矩阵中,则不变换,直接放入加密串中;
4、如果字母对出现在方阵中的同一行或同一列,如fk或ky,则只需简单对调这两个字母,即变换为kf或yk;
5、如果在正方形中能够找到以字母对为顶点的矩形,假如字母对为da,则该矩形的另一对顶点字母中,与d同行的字母应在前面,在上例中应是bq;同样若待变换的字母对为pj,则变换后的字母对应为sg;
6、本程序中输入串均为小写字母,并不含标点、空格或其它字符。


解密方法与加密相同,即对加密后的字符串再加密,将得到原始串。


输入格式如下:
输入为两行字符串,
第一行为密钥单词(长度小于等于25),
第二行为待加密字符串(长度小于等于50),
两行字符串末尾都有一个回车换行符,
并且,两行字符串均为小写字母,不含其它字符。


输出为一行,表示加密后的字符串。


例如:
输入:
lanqiao
dasai


程序应该输出:
bqpqi




再例如:
输入:
dasai
lanqiao


程序应该输出:
ksltaio




资源约定:
峰值内存消耗(含虚拟机) < 256M
CPU消耗  < 1000ms




请严格按要求输出,不要画蛇添足地打印类似:“请您输入...” 的多余内容。


所有代码放在同一个源文件中,调试通过后,拷贝提交该源码。
java选手注意:不要使用package语句。不要使用jdk1.7及以上版本的特性。
java选手注意:主类的名字必须是:Main,否则按无效代码处理。


c/c++选手注意: main函数需要返回0
c/c++选手注意: 只使用ANSI C/ANSI C++ 标准,不要调用依赖于编译环境或操作系统的特殊函数。
c/c++选手注意: 所有依赖的函数必须明确地在源文件中 #include , 不能通过工程设置而省略常用头文件。

 

提交程序时,注意选择所期望的语言类型和编译器类型。

 

 

import java.util.HashSet;
import java.util.Scanner;
import java.util.Set;

public class Main {

	public static void main(String[] args) {
		Scanner sc = new Scanner(System.in);
		String key = sc.nextLine();
		String str = sc.nextLine();
		String[] keys = key.split("");
		String[][] z = new String[5][5];
		key = "";
		Set set = new HashSet();
		for (int i = 0; i < keys.length; i++) { // 去除密钥中重复的字母
			if (set.add(keys[i])) {
				key = key + keys[i];
			}
		}
		set.removeAll(set);
		String[] s = key.split("");
		for (int i = 0; i < s.length; i++) {
			set.add(s[i]);
		}
		for (char c = 97; c < 123; c++) { // 构造方阵字符串
			String cc = c + "";
			if (set.add(cc) && key.length() < 25) {
				key = key + cc;
			}
		}
		keys = key.split("");
		int j = 0;
		int l = 0;
		for (int i = 0; i < keys.length; i++) { // 构造方阵数组
			z[j][l] = keys[i];
			if ((i + 1) % 5 == 0) {
				j++;
				l = 0;
			} else {
				l++;
			}
		}
		// 开始处理加密字符串
		j = 0;
		l = 1;
		int y1 = 0;
		int y2 = 0;
		int x1 = 0;
		int x2 = 0;
		while (l < str.length()) { // 寻找被加密字符串在方阵中的位置
			for (int i = 0; i < 5; i++) {
				for (int k = 0; k < 5; k++) {
					if ((str.substring(j, l)).equals(z[i][k])) {
						y1 = k;
						x1 = i;
					}
					if ((str.substring(l, l + 1)).equals(z[i][k])) {
						y2 = k;
						x2 = i;
					}
				}
			}
			// 根据细则输出加密后的字符串
			if (!(key.contains(str.substring(j, l)) && key.contains(str.substring(l, l + 1)))) {
				System.out.print(str.substring(j, l) + str.substring(l, l + 1));
			} else if (y1 == y2) {
				System.out.print(z[x2][y1] + z[x1][y2]);
			} else {
				System.out.print(z[x1][y2] + z[x2][y1]);
			}
			if (str.length() % 2 != 0 && l + 2 >= str.length()) {
				System.out.print(str.substring(str.length() - 1));
				j += 2;
				l += 2;
			} else {
				j += 2;
				l += 2;
			}
		}
	}
}

 

 

 

 

 

你可能感兴趣的:(蓝桥杯模拟赛高职组试题,数据结构与算法,蓝桥杯)