1316: 矩阵变换加密法
Time Limit: 1 Sec Memory Limit: 128 MBSubmit: 7 Solved: 4
[ Submit][ Status][ Web Board]
Description
一种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),两行字符串末尾都有一个回车换行符,并且两行字符串均为小写字母,不含其它字符。
在标准输出上输出加密后的字符串。
Input
若输入:
youandme
welcometohangzhou
则表示输入的密钥单词为youandme,形成的正方形如上所示;待加密字符串为welcometohangzhou。在正方形中可以找到以第一对字母we为顶点的矩形,对应另一对顶点字母为vb,因此加密后为vb,同理可找到与字母对lc,et,oh,ho对应的顶点字母对。而字母对om位于上述正方形中的同一列,所以直接以颠倒这两个字母来加密,即为mo,字母对an同理。字母对gz中的z不在上述正方形中,因此原样放到加密串中。最后剩一个字母u也原样输出。
Output
输出的结果为:
vbrmmomvugnagzguu
Sample Input
youandme
vbrmmomvugnagzguu
Sample Output
welcometohangzhou
import java.util.*;
public class 矩阵变换加密法 {
static char[] c=new char[256];
static char[] ch=new char[256];
static char[] c1=new char[256];
static char[][] cr=new char[6][6];
//生成矩阵
public static void sj() {
int n=0;
for(int i=0;i<c.length;i++)
if(c[i]>='a'&&c[i]<='z')
n++;
for(int i=0;i<25;i++) {
if(i>=0&&i<n)
c[i]=c[i];
else
c[i]=c1[i-n];
}
for(int i=0;i<c.length;i++) {
if(i>=0&&i<=4)
cr[0][i]=c[i];
if(i>=5&&i<=9)
cr[1][i%5]=c[i];
if(i>=10&&i<=14)
cr[2][i%5]=c[i];
if(i>=15&&i<=19)
cr[3][i%5]=c[i];
if(i>=20&&i<=24)
cr[4][i%5]=c[i];
}
}
//返回该字母在矩阵中的位置
public static int w(char c2) {
int x = 0,y = 0;
for(int i=0;i<5;i++) {
for(int j=0;j<5;j++) {
if(cr[i][j]==c2) {
x=i;
y=j;
}
}
}
return x*5+y;
}
//判断字母是否在矩阵中
public static boolean p(char c2) {
boolean flag=false;
for(int i=0;i<5;i++) {
for(int j=0;j<5;j++) {
if(cr[i][j]==c2)
flag=true;
}
}
return flag;
}
//对生成的矩阵进行处理
public static void d() {
int n=0,j=0,m;
char t;
for(int i=0;i<ch.length;i++) {
if(ch[i]>='a'&&ch[i]<='z')
n++;
}
m=n;
if(m%2!=0)
m=m-1;
while(j<m) {
if(p(ch[j])&&p(ch[j+1])) {
int x1=w(ch[j]);
int x2=w(ch[j+1]);
int x=(x1%5)-(x2%5);
if(x==0) {
t=ch[j];
ch[j]=ch[j+1];
ch[j+1]=t;
}else{
ch[j]=cr[x1/5][x1%5-x];
ch[j+1]=cr[x2/5][x2%5+x];
}
}
j+=2;
}
for(int i=0;i<n;i++)
System.out.print(ch[i]);
}
public static void main(String[] args) {
Scanner in=new Scanner(System.in);
String s="";
int t=0,n=0;
while(t<2) {
s=in.nextLine();
for(int i=0;i<s.length();i++) {
if(t==0)
c[i]=s.charAt(i);
else
ch[i]=s.charAt(i);
}
t++;
}
for(int i='a';i<='z';i++) {
int f=1;
for(int j=0;j<c.length;j++) {
if((char)i==c[j])
f=0;
}
if(f==1)
c1[n++]=(char)i;
}
sj();
d();
}
}