每日一题-加密

mac2024-06-17  42


title: 每日一题–加密 date: 2019-10-31 11:13:59 tags:

每日一题算法

89.加密 (15分) C时间限制:3 毫秒 | C内存限制:3000 Kb 题目内容:

一种Playfair密码变种加密方法如下:首先选择一个密钥单词(称为pair)(字母不重复,且都为小写字母),然后与字母表中其他字母一起填入至一个5x5的方阵中,填入方法如下: 1.首先按行填入密钥串。 2.紧接其后,按字母序按行填入不在密钥串中的字母。 3.由于方阵中只有25个位置,最后剩下的那个字母则不需变换。 如果密钥为youandme,则该方阵如下: y o u a n d m e b c f g h i j k l p q r s t v w x 在加密一对字母时,如am,在方阵中找到以这两个字母为顶点的矩形: o u a m e b

这对字母的加密字母为该矩形的另一对顶点,如本例中为ob。 请设计程序,使用上述方法对输入串进行加密,并输出加密后的串。 另外有如下规定: 1、一对一对取字母,如果最后只剩下一个字母,则不变换,直接放入加密串中; 2、如果一对字母中的两个字母相同,则不变换,直接放入加密串中; 3、如果一对字母中有一个字母不在正方形中,则不变换,直接放入加密串中; 4、如果字母对出现在方阵中的同一行或同一列,如df或hi,则只需简单对调这两个字母,即变换为fd或ih; 5、如果在正方形中能够找到以字母对为顶点的矩形,假如字母对为am,则该矩形的另一对顶点字母中, 与a同行的字母应在前 面,在上例中应是ob;同样若待变换的字母对为ta,则变换后的字母对应为wo; 6、本程序中输入串均为小写字母,并不含标点、空格或其它字符。 解密方法与加密相同,即对加密后的字符串再加密,将得到原始串。 输入描述 从控制台输入两行字符串,第一行为密钥单词(长度小于等于25,字母不重复,且都为小写字母), 第二行为待加密字符串(长度 小于等于50),两行字符串末尾都有一个回车换行符,并且两行字符串均为小写字母,不含其它字符。 输出描述 在标准输出上输出加密后的字符串。 输入样例 youandme welcometohangzhou 输出样例 vbrmmomvugnagzguu


#include <stdio.h> /* pwd:记录密钥 str:用来记录生成的正方形数组 c1: 填入其他字母时的一个变量 str1: 用来记录要加密的字符串 res: 用来记录加密后的字符串 i, j, m: 普通变量 len: 密钥的长度 len1: 待加密字符串的长度 x1 ~ y2: 记录坐标 */ char pwd[26], str[5][5], c1 = 'a', str1[51], res[51]; int i, j, m = 0, len = 0, len1 = 0, x1 = -1, y1, x2 = -1, y2; //判断当前字符是否在某字符串中 int fun(char c){ for(int n = 0; n < len; n++){ if(pwd[n] == c){ return 0; } } return 1; } //找出两个字符在二维数组中的横纵坐标 void fun1(char a, char b){ for(int i = 0; i < 5; i++){ for(int j = 0; j < 5; j++){ if(str[i][j] == a){ x1 = i; y1 = j; } if(str[i][j] == b){ x2 = i; y2 = j; } } } } int main(){ scanf("%s", pwd); for(len = 0; pwd[len]; len++){ } scanf("%s", str1); for(len1 = 0; str1[len1]; len1++){ } // printf("%s\n", pwd); // printf("%s\n", str1); for(i = 0; i < 5; i++){ for(j = 0; j < 5; j++){ //现将密钥填入 if(m < len){ str[i][j] = pwd[m]; m++; continue; } while(!fun(c1)){ c1 = c1 + 1; } str[i][j] = c1; c1 = c1 + 1; } } //打印二维数组 // for(i = 0; i < 5; i++){ // for(j = 0; j < 5; j++){ // printf("%c ", str[i][j]); // } // printf("\n"); // } for(int R = 0; R < len1; R = R + 2){ x1 = -1; x2 = -1; //两个字母相同,则不变换,直接放入加密串中 if(str1[R] == str1[R + 1]){ res[R] = str1[R]; res[R + 1] = str1[R + 1]; }else{ fun1(str1[R], str1[R + 1]); //如果有一个字母不在正方形中,则不变换 if(x1 == -1 || x2 == -1){ res[R] = str1[R]; res[R + 1] = str1[R + 1]; }else{ //同一行或同一列,对调即可 if(x1 == x2 || y1 == y2){ res[R] = str1[R + 1]; res[R + 1] = str1[R]; }else{ res[R] = str[x1][y2]; res[R + 1] = str[x2][y1]; } } } } //最后如果只剩一个字母,直接加入即可 if(len1 % 2 == 1){ res[len1 -1] = str1[len1 -1]; } printf("%s", res); return 0; }

题目不难,但过程比较繁琐,一定要等到思考清楚后再下笔。不能畏惧麻烦,其实细分后来看,每一步都不难,不要被自己给吓倒了。

然后就是关于超时得问题,该简化得地方自己一定要简化,这样会给自己解决掉很多不必要得麻烦。

最后便是全局变量得使用,个人认为,在一定程度上,可以放开使用,这样在写题时就不用将值传来传去,不容易出错。

最新回复(0)