题目描述
二战时期,德军使用了一套名为Enigma的密码系统,是一种基于字符映射的密码系统。它的工作原理如下:
使用者从键盘按下一个字母后,字母会先经过三个可以转动的轮盘,称为转子,每个转子就是一个字符映射表。如:
输入 | A | B | C | D | E |
输出 | D | E | A | B | C |
一个转子的输出作为下一个转子的输入。当经过第三个转子后,输出会被送入到一个反射器。反射器和转子一样,区别在于不能转动,且映射是对称的,即如果输入c1会输出c2,那么输入c2将输出c1。经过反射器后,字母会依次反向进入三个转子,并最终显示在显示盘上。至此算完成了一个字母的加密。当加密下一个字母时,第一个转子会转动一格,转子的转动代表着映射表发生变化。如上表在转动后将变成
输入 | A | B | C | D | E |
输出 | E | A | B | C | D |
当转子转动一周再次回到初始位置时,会带动第二个转子转动一格,同理第二个转动一周后,会带动第三个转子转动。(第三个转子本题中不考虑。)
本题中的三个转子和反射器的结构如下:
转子A:QAZWSXEDCRFVTGBYHNUJMIKOLP
转子B:QWERTYUIOPASDFGHJKLZXCVBNM
转子C:QETUOADGJLZCBMWRYIPSFHKXVN
反射器:ZYXWVUTSRQPONMLKJIHGFEDCBA
使用时三个转子也可拆卸自由调节顺序,也就是说加密操作前的初始状态会有26*26*26*3!种。我们用6位字母来记录初始状态,并称为密钥。1-3位记录三个的转子的排列顺序(如BAC表示B转子放在最靠近键盘的位置)。4-6位记录三个转子的初始位置(如XYZ表示最靠近键盘的转子初始位置在X上)。
现在提供你一串密文和密钥,请给出它的原文。
输入
第一行输入整数n(0<n<10000),代表测试用例的数量。
接下来每个用例由两行组成,第一行由六个大定字母组成,表示密钥。第二行为待解密字符串,由大写字母组成,长度不超过10000。
输出
每一行输出解密后的明文。
样例输入
1ABCXYZ ZDBSF
样例输出
HELLO
提示
来源
1A 2B 3C 4D 5E 6F 7G 8H 9I 10J 11K 12L 13M 14N 15O 16P 17Q 18R 19S 20T 21U 22V 23W 24X 25Y 26Z
第一个转子:
1X 2E 3D 4C 5R 6F 7V 8T 9G 10B 11Y 12H 13N 14U 15J 16M 17I 18K 19O 20L 21P 22Q 23A 24Z 25W 26S
第二个转子:
1Y 2U 3I 4O 5P 6A 7S 8D 9F 10G 11H 12J 13K 14L 15Z 16X 17C 18V 19B 20N 21M 22Q 23W 24E 25R 26T
第三个转子:
1Z 2C 3B 4M 5W 6R 7Y 8I 9P 10S 11F 12H 13K 14X 15V 16N 17Q 18E 19T 20U 21O 22A 23D 24G 25J 26L
反射器:
1Z 2Y 3X 4W 5V 6U 7T 8S 9R 10Q 11P 12O 13N 14M 15L 16K 17J 18I 19H 20G 21F 22E 23D 24C 25B 26A
#include <iostream>
#include <cstring>
#include <cstdio>
using namespace std;
struct password{
char name;
string unit;
};
password a={'A',"QAZWSXEDCRFVTGBYHNUJMIKOLP"};
password b={'B',"QWERTYUIOPASDFGHJKLZXCVBNM"};
password c={'C',"QETUOADGJLZCBMWRYIPSFHKXVN"};
string react="ZYXWVUTSRQPONMLKJIHGFEDCBA",medi,abc="ABCDEFGHIJKLMNOPQRSTUVWXYZ";
void change_first(string &a,char t){
int i;
for(i=0;i<26;i++){
if(a[i]==t){
medi=a.substr(0,i);
break;
}
}
a=a.substr(i,26-i);
a=a+medi;
}
void change1(int &middle,string a){
char t=a[middle];
int i;
for(i=0;i<26;i++){
if(abc[i]==t){
middle=i;
break;
}
}
}
void change2(char &re_middle,string a){
int i;
for(i=0;i<26;i++){
if(a[i]==re_middle){
break;
}
}
re_middle=abc[i];
}
void add1(string &a){
medi=a.substr(0,1);
a=a.substr(1,25);
a=a+medi;
}
int main(){
int i,j,k,n;
string t;
scanf("%d",&n);
while(n--){
password sel[3];
sel[0]=a,sel[1]=b,sel[2]=c;
string zhuanzi[3];
cin>>t;
for(i=0;i<3;i++){
for(j=0;j<3;j++){
if(sel[j].name==t[i]){
zhuanzi[i]=sel[j].unit;
break;
}
}
}
for(i=0;i<3;i++){
change_first(zhuanzi[i],t[3+i]);
}
cin>>t;
k=0;
while(t[k]!='\0'){
int middle;
for(i=0;i<26;i++){
if(abc[i]==t[k]){
middle=i;
break;
}
}
for(i=0;i<3;i++){
change1(middle,zhuanzi[i]);
}
char re_middle=react[middle];
for(i=2;i>=0;i--){
change2(re_middle,zhuanzi[i]);
}
cout<<re_middle;
k++;
add1(zhuanzi[0]);
if(k%26==0&&k!=0){
add1(zhuanzi[1]);
}
if(k%(26*26)==0&&k!=0){
add1(zhuanzi[2]);
}
}
cout<<endl;
}
return 0;
}