用c语言编程 处理文本解密问题


此“暗算”非彼《暗算》 ,虽然我们没有电影中阿柄惊人的听力,可以辨别破译密码,但是我们也可以成为破译专家。

现在就来给大家作一个集训:

改变阿拉伯字母的顺序是文本加密中十分常用的方法,但是并不安全。也就是说,把文本中的每一个阿拉伯字母都要一致地替换成一些其他的字母。为了保证加密的可逆性,需要每个阿拉伯字母都有唯一一个替换的字母(也就说,任意两个阿拉伯字母都不可以用同一个字母来替换)。

最有效的密码分析方法就是“已知明文攻击(known-plaintext attack)”法。在此种方法中,密钥专家掌握着敌方加密的短语或语句,然后通过观察这些加密文字从而推导出译码的方法。

你现在的任务就是来破译几行加密的文本,这些文本是用一条密钥加密的,即某一行加密前就是密钥本身。通常密钥是一个包含了全部 26 个英文字母的字符串,譬如在“暗算 1.0”中,使用的密钥是:

the quick brown fox jumps over the lazy dog
不过一个固定的密钥实在是太容易破译了,只要掌握了规律,就不太费劲。为了能够保证信息的安全性,我们决定在此次集训中,使用可变化的密钥。也就是说,每一组测试用例,都包含着自己的密钥。

输入
首先是单独一个正整数用来说明测试的组数,后边跟着一行字符串,这行字符串就是这次测试用例所使用的密钥。再接着是一个空白行。而且,连续两组测试之间也有一个空白行。

每组测试有多行输入组成。加密的方式如上所示。加密的文本行只包含有小写字母和空格,而且长度不超过 80 个字符。最多有 100 条输入的文本行。

输出
对应每组测试, 解密每一行的信息,并且把标准输出打印出来。如果有多于一种的解密方法,那么任何一种都可以。如果没有解密的方法,则输出信息“No solution.”

每两组测试输出之间必须用一个空白行分隔开。

来源
http://online-judge.uva.es/p/v8/850.html

测试用例
1
the quick brown fox jumps over the lazy dog

vtz ud xnm xugm itr pyy jttk gmv xt otgm xt xnm puk ti xnm fprxq
xnm ceuob lrtzv ita hegfd tsmr xnm ypwq ktj
frtjrpgguvj otvxmdxd prm iev prmvx xnmq
输出
now is the time for all good men to come to the aid of the party
the quick brown fox jumps over the lazy dog
programming contests are fun arent they
我看了看那个英文网站上面的介绍。这是一个已知明文攻击。而且the quick brown fox jumps over the lazy dog包括了全部的26个字母。所以下面我们要找到和the quick brown fox jumps over the lazy dog长度一下的一行,然后还可以判断空格的位戚早置。这样的话就是找的密文。26个字母又全部有对应。问题迎刃而解。不知道我这样解释行吗?程序就不再写了。还有更有意思的,你搜一下the quick brown fox jumps over the lazy dog。这句话很特殊啊。不好意思的是我还是一个一个查的呢!
昨天给你说的你不知道听懂没有?刚刚写兆仔陪了下代码:可以做为参考!感觉可以的话请选我为最佳族蠢答案,不在乎分,只在于劳动是否得到承认。(已经调试成功)#include<stdio.h>
#include<stdlib.h>
#include<string.h>
int main(){
char buf[26];/*用来判断存映射关系*/
char new_buf[80];/*用来存放解密好的*/
memset(buf,0,sizeof(buf));
char buf_plain[3][80]={"vtz ud xnm xugm itr pyy jttk gmv xt otgm xt xnm puk ti xnm fprxq",
"xnm ceuob lrtzv ita hegfd tsmr xnm ypwq ktj",
"frtjrpgguvj otvxmdxd prm iev prmvx xnmq"};
char buf_mingwen[]="the quick brown fox jumps over the lazy dog";
int num;/*用来记录buf_mingwen的长度*/
num=strlen(buf_mingwen);
int i,j;
int line=0;/*记录最终匹配的行*/
int flag=1;
/*下面开始寻找密钥*/
for(i=0;i<3&&flag;i++){
if(strlen(buf_mingwen)!=strlen(buf_plain[i]))continue;/*长度不等直接挑过*/
else{
for(j=0;j<strlen(buf_plain[i]);j++){
if(buf_plain[i][j]!=' '){
if((buf[ buf_plain[i][j]-'a'])==0)
buf[ buf_plain[i][j]-'a']=buf_mingwen[j];
else{
if( buf[ buf_plain[i][j]-'a']!=buf_mingwen[j])break;/*映射未成功*/
else{ if(j==num-1){line=i;flag=0;break; }}
}
}

}

}

}
/*下面开始解密每行打印一次*/
for(i=0;i<3;i++){
for(j=0;j<strlen(buf_plain[i]);j++){
if(buf_plain[i][j]==' ')new_buf[j]=' ';
else new_buf[j]=buf[buf_plain[i][j]-'a'];
}
printf("%s\n",new_buf);
memset(new_buf,0,sizeof(new_buf));
}
}