描述
R国和S国正陷入战火之中,双方都互派间谍,潜入对方内部,伺机行动。
历经艰险后,潜伏于S国的R国间谍小C终于摸清了S国军用密码的编码规则:
1、 S国军方内部欲发送的原信息经过加密后在网络上发送,原信息的内容与加密后所的内容均由大写字母‘A’—‘Z’构成(无空格等其他字母)。
2、 S国对于每个字母规定了对应的“密字”。加密的过程就是将原信息中的所有字母替换为其对应的“密字”。
3、 每个字母只对应一个唯一的“密字”,不同的字母对应不同的“密字”。“密字”可以和原字母相同。
例如,若规定‘A’的密字为‘A’,‘B’的密字为‘C’(其他字母及密字略),则原信息“ABA”被加密为“ACA”。
现在,小C通过内线掌握了S国网络上发送的一条加密信息及其对应的原信息。小C希望能通过这条信息,破译S国的军用密码。小C的破译过程是这样的:扫描原信息,对于原信息中的字母x(代表任一大写字母),找到其在加密信息中的对应大写字母y,并认为在密码里y是x的密字。如此进行下去直到停止于如下的某个状态:
1、 所有信息扫描完毕,‘A’—‘Z’所有26个字母在原信息中均出现过并获得了相应的“密字”。
2、 所有信息扫描完毕,但发现存在某个(或某些)字母在原信息中没有出现。
3、 扫描中发现掌握的信息里有明显的自相矛盾或错误(违反S国密码的编码规则)。例如某条信息“XYZ”被翻译为“ABA”就违反了“不同字母对应不同密字”的规则。
在小C忙得头昏脑胀之际,R国司令部又发来电报,要求他翻译另外一条从S国刚刚截取到的加密信息。现在请你帮助小C:通过内线掌握的信息,尝试破译密码。然后利用破译的密码,翻译电报中的加密信息。
输入
共3行,每行为一个长度在1到100之间的字符串。
第1行为小C掌握的一条加密信息。
第2行为第1行的加密信息所对应的原信息。
第3行为R国司令部要求小C翻译的加密信息。
输入数据保证所有字符串仅由大写字母‘A’—‘Z’构成,且第1行长度与第2行相等。
输出
共1行。
若破译密码停止时出现2,3两种情况,请你输出“Failed”(不含引号,注意首字母大写,其它小写)。
否则请输出利用密码翻译电报中加密信息后得到的原信息。
样例输入
样例 #1:
AA
AB
EOWIE
样例 #2:
QWERTYUIOPLKJHGFDSAZXCVBN
ABCDEFGHIJKLMNOPQRSTUVWXY
DSLIEWO
样例 #3:
MSRTZCJKPFLQYVAWBINXUEDGHOOILSMIJFRCOPPQCEUNYDUMPP
YIZSDWAHLNOVFUCERKJXQMGTBPPKOIYKANZWPLLVWMQJFGQYLL
FLSO
样例输出
样例 #1:
Failed
样例#2:
Failed
样例#3:
NOIP
提示
输入输出样例1说明:原信息中的字母‘A’和‘B’对应相同的密字,输出“Failed”。
输入输出样例2说明:字母‘Z’在原信息中没有出现,输出“Failed”。
思路:
首先题目的意思大概就是,通过密文和原文解析加密原则,要么把26个字母的加密原则都解析出来然后解密司令发来的密文,要么解析失败,同时解析失败有两种情况,一种是没有凑齐
26个字母,一种是同一个密文等于不同的原文或者同一个原文等于不同的密文这两种矛盾情况。
然后我们需要思考是先检查有没有矛盾还是先检查有没有26个字母,我个人后者更简单一些,所以先检查有没有26个字母再检查有没有矛盾。
//建议复制到编程软件中查看
#include<stdio.h>
#include<string.h>
int main()
{
int i,j=0,k=0,len,lenn,cnt=0;
//用 len记录密文的长度(原文和密文一样长),lenn 记录司令发来的密文的长度,cnt用来判断情况
char m[101]={0},y[101]={0},s[101]={0},z[27]={0};
//m[101]记录密文,y[101]记录原文,s[101]记录司令发来的密文,z[27]用来统计是否凑齐了26个字母
gets(m);
gets(y);
gets(s);
len=strlen(m);
lenn=strlen(s);
/*先判断是否凑齐26个字母,大致思路为,z[27]一开始全部是 '\0',我们每找到一个新的字母就将其放入z[27]中,然后每个字母在放入前都先遍历z看是否已经有了该字母,
如果有了就直接退出遍历,最后通过z[27]的有效长度来判断是否凑齐26个字母,用原文或者密文检查都可以,我这里选择用原文检查*/
for(i=0;i<len;i++){
for(j=0;z[j]!='\0';j++){
if(y[i]==z[j]){ //y[i]==z[j]表示 z中已经存在y[i]这个字母了,不需要在往后检查了
cnt=1;
break;
}
}
if(cnt==0){ //表示 z中还没有该字母
z[k]=y[i]; //将其存入 z中
k++;
}
cnt=0; //每次检查完一个原文的字母 cnt需要重置,可以自己调试感知一下
}
if(strlen(z)<26){ //有效长度小于26,表示没有凑齐26个字母,解析失败
printf("Failed\n");
return 0;
}
if(strlen(z)==26){ //有效长度等于26,表示凑齐了26个字母,下面检查是否有两种矛盾情况
for(i=0;i<len;i++){
for(j=0;j!=i&&j<len;j++){ // j!=i 避开了自己等于自己的情况
if((m[i]==m[j]&&y[i]!=y[j])||(y[i]==y[j]&&m[i]!=m[j])){ //前者为同一密文对应的原文不相同,后者为同一原文对应的密文不相同,发现其一直接解析失败
printf("Failed\n");
return 0;
}
}
}
}
//解析成功,开始解密司令发来的密文
for(i=0;i<lenn;i++){
for(j=0;j<len;j++){
if(s[i]==m[j]){ //进行解密,如果 s[i]与密文 m[j]相同
s[i]=y[j]; //那就将 s[i]解密为 m[j]对应的 y[j]
break;
}
}
}
puts(s); //输出解密后的司令密文
return 0;
}