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
其一变种方法如下:首先选择一个密钥单词(称为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。
这对字母的加密字母为该矩形的另一对顶点,如本例中为bq。
请设计程序,使用上述方法对输入串进行加密,并输出加密后的串。
另有细则如下:
1、一对一对取字母,如果最后只剩下一个字母,则不变换,直接放入加密串中;
2、如果一对字母中的两个字母相同,则不变换,直接放入加密串中;
3、如果一对字母中有一个字母不在矩阵中,则不变换,直接放入加密串中;
4、如果字母对出现在方阵中的同一行或同一列,如fk或ky,则只需简单对调这两个字母,即变换为kf或yk;
5、如果在正方形中能够找到以字母对为顶点的矩形,假如字母对为da,则该矩形的另一对顶点字母中,与d同行的字母应在前面,在上例中应是bq;同样若待变换的字母对为pj,则变换后的字母对应为sg;
6、本程序中输入串均为小写字母,并不含标点、空格或其它字符。
1、一对一对取字母,如果最后只剩下一个字母,则不变换,直接放入加密串中;
2、如果一对字母中的两个字母相同,则不变换,直接放入加密串中;
3、如果一对字母中有一个字母不在矩阵中,则不变换,直接放入加密串中;
4、如果字母对出现在方阵中的同一行或同一列,如fk或ky,则只需简单对调这两个字母,即变换为kf或yk;
5、如果在正方形中能够找到以字母对为顶点的矩形,假如字母对为da,则该矩形的另一对顶点字母中,与d同行的字母应在前面,在上例中应是bq;同样若待变换的字母对为pj,则变换后的字母对应为sg;
6、本程序中输入串均为小写字母,并不含标点、空格或其它字符。
解密方法与加密相同,即对加密后的字符串再加密,将得到原始串。
输入格式如下:
输入为两行字符串,
第一行为密钥单词(长度小于等于25),
第二行为待加密字符串(长度小于等于50),
两行字符串末尾都有一个回车换行符,
并且,两行字符串均为小写字母,不含其它字符。
输入为两行字符串,
第一行为密钥单词(长度小于等于25),
第二行为待加密字符串(长度小于等于50),
两行字符串末尾都有一个回车换行符,
并且,两行字符串均为小写字母,不含其它字符。
输出为一行,表示加密后的字符串。
例如:
输入:
lanqiao
dasai
输入:
lanqiao
dasai
程序应该输出:
bqpqi
bqpqi
注:
该题,接触为视频中,接触。相关代码测试,已知的全部通过了。但是测试过,因为没找到相关平台,在此阐述我的想法,和我个人代码。
我的思路,就是存储起来。
第一个:通过判断某位置字母是不是为0,判断存不存在;
第二个:每一个字母的位置,我都是认为理解的坐标记录,比如:x1 = 2,y1 = 5,表示第二行第五个,但是在一维数组中为20,故位置为(x1 - 1)*5+y1; 逆着推就是判断是不是5的倍数,如果是的话,就是x1 = sum/5,y1 = 5,不是的话,那就是x1 = sum/5+1,y1 = sum - sum/5*5;
第三个:同行同列的话,直接就可以判断了,很清晰!
第四个:交换,交换原则是str_mima[i],要等于同行的那个,str_mima[i+1]要等于另外一个。
代码如下:
#include <iostream>
#include <stdio.h>
#include <string.h>
#include <algorithm>
using namespace std;
/*
第一步;先存储
注意点:重复点,第二点未出现的点
第二步:加密字母的解密
注意点:对角线,同行,同列
测试点:
输入:
youandme
welcometohangzhou
输出:
vbrmmomvugnagzguu
*/
int main()
{
int f[30];
char str_key[30],str_mima[55],search[30];
gets(str_key);
gets(str_mima);
///第一步存储
memset(f,0,sizeof(f));
int t = 1;
int len_key = strlen(str_key);
for(int i=0; i<len_key; i++)
{
if(f[str_key[i]-'a'+1] != 0)
continue;
search[t] = str_key[i];
f[str_key[i]-'a'+1] = t;
t++;
}
int sum = 0;
for(int i=t; i<=25; i++)
{
while(f[sum+1]!=0 && sum<26)
sum++;
search[i] = sum+'a';
f[sum+1] = i;
}
// for(int i=1; i<=25; i++)
// {
// printf("%c ",search[i]);
// if(i%5==0 && i!=0) printf("\n");
// }
//
// for(int i=1; i<=25; i++)
// {
// printf("%c:%d ",i+'a'-1,f[i]);
// if(i%5==0 && i!=0) printf("\n");
// }
int len_mima = strlen(str_mima);
///for范围0到len_mima-1,因为第一个防止超界,第二个如果是单数,最后一个不要进行交换处理
for(int i=0;i<len_mima-1;i+=2)
{
///x1,y1,x2,y2表示的是str_mima[i],str_mima[i+!]在prime的位置。
int x1 = f[str_mima[i]-'a'+1]%5==0?f[str_mima[i]-'a'+1]/5:f[str_mima[i]-'a'+1]/5+1;
int y1 = (f[str_mima[i]-'a'+1] - f[str_mima[i]-'a'+1]/5*5)==0?5:(f[str_mima[i]-'a'+1] - f[str_mima[i]-'a'+1]/5*5);
int x2 = (f[str_mima[i+1]-'a'+1]%5)==0?f[str_mima[i+1]-'a'+1]/5:f[str_mima[i+1]-'a'+1]/5+1;
int y2 = (f[str_mima[i+1]-'a'+1] - f[str_mima[i+1]-'a'+1]/5*5)==0?5:(f[str_mima[i+1]-'a'+1] - f[str_mima[i+1]-'a'+1]/5*5);
// printf("%d %d %d %d\n",x1,y1,x2,y2);
///如果不存在这个字母,将不交换
if(f[str_mima[i]-'a'+1]==0 || f[str_mima[i+1]-'a'+1] == 0)
continue;
///同行或者是同列
if(y1 == y2 || x1 == x2)
{
char t = str_mima[i];
str_mima[i] = str_mima[i+1];
str_mima[i+1] = t;
}else{
str_mima[i] = search[(x1-1)*5+y2];
str_mima[i+1] = search[(x2-1)*5+y1];
}
}
puts(str_mima);
return 0;
}
如果转载请注明转载地址为:http://blog.csdn.net/ZJWSA/article/details/79592437