Playing Fair with Cryptography
Time Limit: 1000MS Memory limit: 65536K
题目描述

You encrypt a digraph using the following rules:
1. If both letters are in the same row, replace each with the letter to its immediate right (wrapping around at the end). For example, using the above grid the plaintext digraph DS is encrypted as FB, and AP is encrypted as PE.
2. If both letters are in the same column, replace each with the letter immediately below it (again wrapping around at the bottom). For example, PF is encrypted as IU (or JU), and WO is encrypted as CS.
3. Otherwise, “slide” the first character across its row until it is in the same column as the second character, and do the same for the second character. The two characters you end up on are the encrypted characters of the digraph. If you view the original digraph as corners of a rectangle in the grid, you are replacing them with the characters in the other two corners. For example, TU is encrypted as FH, UT is encrypted as HF, and ZC is encrypted as WP.
What happens when the digraph contains the same letter twice? In the original Playfair cipher you insert the letter ‘X’ between the two letters and continue encrypting. You also use an extra `X\' at the end of the plaintext if you have an odd number of letters. Thus the plaintext "OOPS" would first be changed to the digraphs "OX", "OP" and "SX" and then would be encrypted as "GWICBW" (using the grid above). Note that the plaintext "POOS" would not need any added letters since the two‘O’s do not appear in the same digraph.
We\'ll modify the Playfair cipher in one simple way: Instead of always using ‘X’ as the inserted letter, use‘A’ the first time an insertion is needed, then \'B\' the next time, and so on (though you should never use ‘J’ as an inserted letter; just go from ‘I\' to \'K\'). Once you hit \'Z\', you go back to using \'A\'. If the inserted letter would result in a digraph with the same two letters, you just skip to the next inserted letter. For example, “OOPS” would now become the digraph stream“OA”, “OP”, ”SB” before being encrypted, and the plaintext “AABCC” would become the digraph stream “AB”, “AB”, “CD”, “CE”.
Given a key and plaintext, you are to generate the corresponding ciphertext.
输入
输出
示例输入
1 ECNA Programming Contest 2013 This is the easy problem!
示例输出
Case 1: HVOFOFHVCPCPDWEIGSHNGD
提示
来源
http://acm.sdut.edu.cn/sdutoj/showproblem.php?pid=2720&cid=1203
这个题其实挺水的,但是一些转化方面的细节我处理的不好WA了好多次。
另外注意和J有关的都要跳过。
#include <cstdio>
#include <iostream>
#include <cstring>
#include <algorithm>
#include <map>
#define MAXN 10005
#define INF 2139062143
#define inf -2139062144
#define ll long long
using namespace std;
map<char,int> mp1;
map<int,char> mp2;
void Convers(char a,char b,char &aa,char &bb)
{
if(a=='J') a='I';
if(b=='J') b='I';
int x=mp1[a],y=mp1[b];
if((x-1)/5==(y-1)/5) //同行
{
int xx=x+1,yy=y+1;
if((xx-1)/5>(x-1)/5) xx=xx-5;
if((yy-1)/5>(y-1)/5) yy=yy-5;
aa=mp2[xx];
bb=mp2[yy];
return ;
}
if((x-1)%5==(y-1)%5) //同列
{
int xx=x+5,yy=y+5;
if((xx-1)/5>=5) xx=(x-1)%5+1;
if((yy-1)/5>=5) yy=(y-1)%5+1;
aa=mp2[xx];
bb=mp2[yy];
return ;
}
int xx=(x-1)/5*5+(y-1)%5+1,yy=(y-1)/5*5+(x-1)%5+1;
aa=mp2[xx];
bb=mp2[yy];
}
int main()
{
int T,kase=0;
scanf("%d",&T);
getchar();
while(T--)
{
mp1.clear();
mp2.clear();
char s1[MAXN]={0},s2[MAXN]={0};
gets(s1);
gets(s2);
int flag=0;
for(int i=0; s1[i]; ++i)
{
if(isalpha(s1[i]))
{
char t=toupper(s1[i]);
if(!mp1[t])
{
++flag;
mp1[t]=flag;
mp2[flag]=t;
}
}
}
for(int i=0; i<26; ++i)
{
char t='A'+i;
if(t=='J') continue;
if(!mp1[t])
{
++flag;
mp1[t]=flag;
mp2[flag]=t;
}
}
mp1['J']=mp1['I'];
char str[MAXN]= {0};
int len=0;
for(int i=0; s2[i]; ++i)
if(isalpha(s2[i]))
{
char t=toupper(s2[i]);
str[len++]=t;
}
str[len]=0;
int use=0;
char ans[MAXN]= {0};
int l=0;
char aa,bb;
for(int i=0; i<len;)
{
use=use%26;
if(i==len-1)
{
while((use%26)+'A'==str[i]||((use%26)+'A'=='J')) use++;
Convers(str[i],(use%26)+'A',aa,bb);
ans[l++]=aa;
ans[l++]=bb;
use++;
i++;
}
else
{
if(str[i]==str[i+1])
{
while((use%26)+'A'==str[i]||((use%26)+'A'=='J')) use++;
Convers(str[i],(use%26)+'A',aa,bb);
ans[l++]=aa;
ans[l++]=bb;
use++;
i++;
}
else
{
Convers(str[i],str[i+1],aa,bb);
ans[l++]=aa;
ans[l++]=bb;
i+=2;
}
}
}
ans[l]=0;
printf("Case %d: ",++kase);
puts(ans);
}
return 0;
}
本文介绍了一种基于Playfair密码的变体加密方法,并通过示例详细解释了其加密过程。该方法不仅保留了原始Playfair密码的基本原理,还引入了新的字母插入规则来增强加密效果。

2265

被折叠的 条评论
为什么被折叠?



