P1071 潜伏者
题目描述
RR 国和 SS 国正陷入战火之中,双方都互派间谍,潜入对方内部,伺机行动。历尽艰险后,潜伏于 SS 国的 RR 国间谍小 CC终于摸清了 SS 国军用密码的编码规则:
1. SS 国军方内部欲发送的原信息经过加密后在网络上发送,原信息的内容与加密后所得的内容均由大写字母‘ AA ’-‘ ZZ ’构成(无空格等其他字符)。
2. SS 国对于每个字母规定了对应的“密字”。加密的过程就是将原信息中的所有字母替换为其对应的“密字”。
3. 每个字母只对应一个唯一的“密字”,不同的字母对应不同的“密字”。“密字”可以和原字母相同。
例如,若规定‘ AA ’的密字为‘ AA ’,‘ BB ’的密字为‘ CC ’(其他字母及密字略),则原信息“ ABAABA ”被加密为“ ACAACA ”。
现在,小 CC 通过内线掌握了 SS 国网络上发送的一条加密信息及其对应的原信息。小 CC 希望能通过这条信息,破译 SS 国的军用密码。小 CC 的破译过程是这样的:扫描原信息,对于原信息中的字母 xx (代表任一大写字母),找到其在加密信息中的对应大写字母 yy ,并认为在密码里 yy 是 xx 的密字。如此进行下去直到停止于如下的某个状态:
1. 所有信息扫描完毕,‘ AA ’-‘ ZZ ’ 所有 2626 个字母在原信息中均出现过并获得了相应的“密字”。
2. 所有信息扫描完毕,但发现存在某个(或某些)字母在原信息中没有出现。
3. 扫描中发现掌握的信息里有明显的自相矛盾或错误(违反 SS 国密码的编码规则)。例
如某条信息“ XYZXYZ ”被翻译为“ ABAABA ”就违反了“不同字母对应不同密字”的规则。
在小 CC 忙得头昏脑涨之际, RR 国司令部又发来电报,要求他翻译另外一条从 SS 国刚刚截取到的加密信息。现在请你帮助小 CC :通过内线掌握的信息,尝试破译密码。然后利用破译的密码,翻译电报中的加密信息。
输入输出格式
输入格式:
共 33 行,每行为一个长度在 11 到 100100 之间的字符串。
第 11 行为小 CC 掌握的一条加密信息。
第 22 行为第 11 行的加密信息所对应的原信息。
第 33 行为 RR 国司令部要求小 CC 翻译的加密信息。
输入数据保证所有字符串仅由大写字母‘ AA ’-‘ ZZ ’构成,且第 11 行长度与第 22 行相等。
输出格式:
共 11 行。
若破译密码停止时出现 2,32,3 两种情况,请你输出“ FailedFailed ”(不含引号,注意首字母大
写,其它小写)。
否则请输出利用密码翻译电报中加密信息后得到的原信息。
输入输出样例
MSRTZCJKPFLQYVAWBINXUEDGHOOILSMIJFRCOPPQCEUNYDUMPP
YIZSDWAHLNOVFUCERKJXQMGTBPPKOIYKANZWPLLVWMQJFGQYLL
FLSO
NOIP
说明
【输入输出样例 11 说明】
原信息中的字母‘ AA ’和‘ BB ’对应相同的密字,输出“ FailedFailed ”。
【输入输出样例 22 说明】
字母‘ ZZ ’在原信息中没有出现,输出“ FailedFailed ”。
NOIP 2009 提高组 第一题
我希望我今天能是红色的。
红一方面军:
这个题需要注意的就是认真读题。
刚开始我的思路是这样的:
输入三个字符串之后,枚举,用一个f数组来记录密字x[i]对应的原信息为y[i],
然后用一个bool b数组记录这个密字是否出现过,(细心的认真读题的应该已经发现有问题了,别着急,慢慢来)
如果没有出现过,就将b置为1,a++。a是记录26个字母是否全都出现的。
然后如果b对应的已经被置为1了的话,那就看看这个已经被记录过的密字对应的原信息是不是和之前对应的一样,
不一样,直接输出failed就好了,一样的话则继续。
枚举完之后,先看看a记录的字母是否是26,也就是26个字母是否全都出现了,如果没有的话,也直接输出failed就好了。
然后没有什么特殊情况的话,就循环输出出入的第三个密字字符数组对应的原信息就好了,
以上思路的代码。
1 #include<iostream> 2 #include<cstdio> 3 #include<cmath> 4 #include<algorithm> 5 #include<cstring> 6 using namespace std; 7 8 char x[102],y[102],c[102],f[92]; 9 bool b[92]; 10 int a; 11 12 int main() 13 { 14 cin>>x; 15 cin>>y; 16 cin>>c; 17 int len=strlen(x),l=strlen(c); 18 for(int i=0;i<len;++i) 19 { 20 if(!b[x[i]]) 21 { 22 f[x[i]]=y[i]; 23 b[x[i]]=1; 24 a++; 25 } 26 else if(f[x[i]]!=y[i]) 27 { 28 printf("Failed"); 29 return 0; 30 } 31 } 32 if(a!=26) 33 { 34 printf("Failed"); 35 return 0; 36 } 37 for(int i=0;i<l;++i) 38 cout<<f[c[i]]; 39 }
这就是我第一次提交的,
90分。
没过的样例是这个:
input:
QWERTYUIOPLKJHGFDSAZXCVBNM
QWERTYUIOPLKJHGFDSAZXCVBNN
HIJACK
output:
Failed
因为原信息中(第二个字符串表示原信息)没有出现M,所以要输出failed。
再仔细看看代码。
看看题目要求,第2个状态要求原信息中应出现所有26个字母,而上面代码bool b数组记录的却是x密字的出现,
a++也是在此条件下的,所以不对。
其实反过来就好了,bool记录条件将x变为y。
ac代码
#include<iostream> #include<cstdio> #include<cmath> #include<algorithm> #include<cstring> using namespace std; char x[102],y[102],c[102],f[92]; bool b[92]; int a; int main() { cin>>x; cin>>y; cin>>c; int len=strlen(x),l=strlen(c); for(int i=0;i<len;++i) { if(!b[y[i]]) { f[x[i]]=y[i]; b[y[i]]=1; a++; } else if(f[x[i]]!=y[i]) { printf("Failed"); return 0; } } if(a!=26) { printf("Failed"); return 0; } for(int i=0;i<l;++i) { cout<<f[c[i]]; } }