背景
此“暗算”非彼《暗算》 ;-) ,虽然我们没有电影中阿柄惊人的听力,可以辨别破译密码,但是我们也可以成为破译专家。
现在就来给大家作一个集训:
改变阿拉伯字母的顺序是文本加密中十分常用的方法,但是并不安全。也就是说,把文本中的每一个阿拉伯字母都要一致地替换成一些其他的字母。为了保证加密的可逆性,需要每个阿拉伯字母都有唯一一个替换的字母(也就说,任意两个阿拉伯字母都不可以用同一个字母来替换)。
最有效的密码分析方法就是“已知明文攻击(known-plaintext attack)”法。在此种方法中,密钥专家掌握着敌方加密的短语或语句,然后通过观察这些加密文字从而推导出译码的方法。
你现在的任务就是来破译几行加密的文本,这些文本是用一条密钥加密的,即某一行加密前就是密钥本身。密钥是一个包含了全部 26 个英文字母的字符串,譬如在“暗算 1.0”中,使用的密钥是:
the quick brown fox jumps over the lazy dog
不过一个固定的密钥实在是太容易破译了,只要掌握了规律,就不太费劲。为了能够保证信息的安全性,我们决定在此次集训中,使用可变化的密钥。也就是说,每一组测试用例,都包含着自己的密钥。
输入
首先是单独一个正整数用来说明测试的组数,后边跟着一行字符串,这行字符串就是这次测试用例所使用的密钥。再接着是一个空白行。而且,连续两组测试之间也有一个空白行。
每组测试有多行输入组成。加密的方式如上所示。加密的文本行只包含有小写字母和空格,而且长度不超过 200 个字符。最多有 100 条输入的文本行。
输出
对应每组测试, 解密每一行的信息,并且把标准输出打印出来。如果有多于一种的解密方法,那么任何一种都可以。如果没有解密的方法,则输出信息“No solution.”
每两组测试输出之间必须用一个空白行分隔开。
来源
http://online-judge.uva.es/p/v8/850.html
测试输入 | 期待的输出 | 时间限制 | 内存限制 | 额外进程 | |
---|---|---|---|---|---|
测试用例 1 | 以文本方式显示
| 以文本方式显示
| 1秒 | 1024KB | 0 |
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
char str[201];
char buf[101][201];
char mask[2][30];
int num, len, i;
int flag;
int main()
{
// freopen("F:in.txt", "r", stdin);
// freopen("F:out.txt", "w", stdout);
scanf("%d", &num);
getchar();
gets(str);//取密钥
getchar();//取空行
while (num--)
{
int index = 0;
len = strlen(str);
flag = 1;
while (1)// 在密文中寻找密钥
{
int p;
if (gets(buf[index]) == NULL)
break;
if (strlen(buf[index]) ==0)// 遇到空白行,还没找到密钥
break;
if (len == strlen(buf[index])&&flag)
{
p = 0;
for (int t = 0; t < 26; t++)
mask[0][t] = '0';
for (i=0; i<len; i++)
{
if (str[i] == ' ')
{
if (buf[index][i] == ' ')
continue;
else
break;
}
if (buf[index][i] == ' ')
break;
if (mask[0][buf[index][i] - 'a'] == '0')
{
mask[0][buf[index][i] - 'a'] ++;
mask[1][buf[index][i] - 'a'] = str[i];
p++;
}
else if (mask[1][buf[index][i] - 'a'] != str[i])//不符合已知的规律,就是错的。
break;
}
}
if (str[i] == '\0')
{
int k, t;
for (i = 0; i<25; i++)
for (t = i + 1; t<26; t++)
if (mask[1][i] == mask[1][t])
break;
if (i == 25 && t == 26) flag = 0;
}
index++;
}
if (flag)
{
printf("No solution.\n");
if (num!=0)
printf("\n");
continue;
}
for (int k = 0; k < index;k++)//解密
{
len = strlen(buf[k]);
for (int t = 0; t < len; t++)
{
if (buf[k][t] != ' ')
printf("%c", mask[1][buf[k][t] - 'a']);
else
printf("%c", buf[k][t]);
}
printf("\n");
}
if (num != 0)
printf("\n");
}
return 0;
}