大家帮我看一个OpenJudge题目——古代密码

tianshilei1992 2012-08-03 03:57:10
不知道测试用例都有什么,但是我觉得这个程序应该没问题的啊……
描述
古罗马帝王有一个包括各种部门的强大政府组织。其中有一个部门就是保密服务部门。为了保险起见,在省与省之间传递的重要文件中的大写字母是加密的。当时最流行的加密方法是替换和重新排列。
替换方法是将所有出现的字符替换成其它的字符。有些字符会碰巧替换成它自己。例如:替换规则可以是将'A' 到 'Y'替换成它的下一个字符,将'Z'替换成 'A',如果原词是 "VICTORIOUS" 则它变成 "WJDUPSJPVT"。
排列方法改变原来单词中字母的顺序。例如:将顺序 <2, 1, 5, 4, 3, 7, 6, 10, 9, 8> 应用到 "VICTORIOUS" 上,则得到"IVOTCIRSUO"。
人们很快意识到单独应用替换方法或排列方法,加密是很不保险的。但是如果结合这两种方法,在当时就可以得到非常可靠的加密方法。所以,很多重要信息先使用替换方法加密,再将加密的结果用排列的方法加密。用两中方法结合就可以将"VICTORIOUS" 加密成"JWPUDJSTVP"。
考古学家最近在一个石台上发现了一些信息。初看起来它们毫无意义,所以有人设想它们可能是用替换和排列的方法被加密了。人们试着解读了石台上的密码,现在他们想检查解读的是否正确。他们需要一个计算机程序来验证她,你的任务就是写这个验证程序。
输入
输入有两行。第一行是石台上的文字。文字中没有空格,并且只有大写英文字母。第二行是被解读出来的加密前的文字。第二行也是由大写英文字母构成的。
两行字符数目的长度都不超过计划100。
输出
如果第二行经过某种加密方法后可以产生第一行的信息,输出 "YES",否则输出"NO"。
样例输入
JWPUDJSTVP
VICTORIOUS
样例输出
YES
我用C++写的,我的思路是,对加密前的文字进行排序,然后测试各个加密后的文字,但是总是Wrong Answer……请大家帮忙看下。

#include <iostream>
#include <algorithm>
#include <string>

using namespace std;

int main(void)
{
string code, org, tmp;
cin >> code >> org;
sort(org.begin(), org.end());
int f = 0;
for (int j = 1; j <= 25; j++)
{
tmp = code;
for (int i = 0; tmp[i] != '\0'; i++)
{
if (tmp[i] - j < 65)
tmp[i] += 26 - j;
else
tmp[i] -= j;
}
sort(tmp.begin(), tmp.end());
if (org == tmp)
{
cout << "YES" << endl;
f = 1;
break;
}
}
if (f == 0)
cout << "NO" << endl;
return 0;
}
...全文
422 7 打赏 收藏 转发到动态 举报
写回复
用AI写文章
7 条回复
切换为时间正序
请发表友善的回复…
发表回复
tianshilei1992 2012-08-07
  • 打赏
  • 举报
回复
[Quote=引用 5 楼 的回复:]

楼主,下面给出我的想法和代码,请检验:
将原码中的每个字符编码后(就是变成它后面的字符),映射到一个大小为26的整型数组中(数组初始化元素都为0),存在的话就加1,即 array[变码后字符-'A'] ++; 然后将密码中的字符同样映射到数组 array 中,存在的话就减1,即 array[密码中的字符-'A'] --; 最后检测 array 中的元素,如果全为0,则输出 YES,否则输出 N……
[/Quote]

你的也是Wrong Answer哦……
tianshilei1992 2012-08-07
  • 打赏
  • 举报
回复
[Quote=引用 5 楼 的回复:]

楼主,下面给出我的想法和代码,请检验:
将原码中的每个字符编码后(就是变成它后面的字符),映射到一个大小为26的整型数组中(数组初始化元素都为0),存在的话就加1,即 array[变码后字符-'A'] ++; 然后将密码中的字符同样映射到数组 array 中,存在的话就减1,即 array[密码中的字符-'A'] --; 最后检测 array 中的元素,如果全为0,则输出 YES,否则输出 N……
[/Quote]
我也是通过数组映射的,我是统计每个字符出现的次数,咱俩的思路应该差不多吧?我试试你的代码看看能否A过。谢谢~
kingxuke 2012-08-06
  • 打赏
  • 举报
回复
楼主,下面给出我的想法和代码,请检验:
将原码中的每个字符编码后(就是变成它后面的字符),映射到一个大小为26的整型数组中(数组初始化元素都为0),存在的话就加1,即 array[变码后字符-'A'] ++; 然后将密码中的字符同样映射到数组 array 中,存在的话就减1,即 array[密码中的字符-'A'] --; 最后检测 array 中的元素,如果全为0,则输出 YES,否则输出 NO。下面是代码和测试例子:

#include <iostream>
#include <algorithm>
#include <string>

using namespace std;

int main(void)
{
string code, org;
cin >> code >> org;

bool flag = true;
unsigned int i = 0;
int index = 0;
int array[26] = {0};

for (i=0; i<org.size(); i++)
{
// index = (org[i] - 'A' + 1) % 26;
index = ( org[i] == 'Z' ? 0 : (org[i] - 'A' + 1) );
array[index] ++;
}

for (i=0; i<code.size(); i++)
{
index = code[i] - 'A';
array[index] --;
}

for (i=0; i<26; i++)
{
if (array[i] != 0)
{
flag = false;
break;
}
}

if (flag)
{
cout << "YES" << endl;
}
else
{
cout << "NO" << endl;
}

return 0;
}
// 测试例子
/*
JWPUDJSTVP
VICTORIOUS
YES
请按任意键继续. . .
*/

楼主,Good Luck!
兆帅 2012-08-06
  • 打赏
  • 举报
回复
你的替换规则很简单,我想可以这样做:对加密后的文字处理,反推出其未加密前的字符,然后xuhu循环遍历原始数据,看是否可以找到推出的数据,循环跌价变量,看最终结果和第一行的字符个数是否相同,相同则表明加密是可行的,否则是没有这种算法,你还可以记录下两次的索引,推出加密的顺序.
tianshilei1992 2012-08-06
  • 打赏
  • 举报
回复
自己顶啊!我又重新写了一个,还是不对啊……

#include <stdio.h>
#include <string.h>

void init(int *count)
{
int i;
for (i = 0; i < 26; i++)
count[i] = 0;
}

int isEqual(int* count1, int* count2)
{
int i;
for (i = 0; i < 26; i++)
if (count1[i] != count2[i])
return 0;
return 1;
}

int main(void)
{
int i, j;
int count1[26], count2[26];
char code[101], org[101], tmp[101];
scanf("%s %s", code, org);
init(count1);
for (i = 0; code[i] != '\0'; i++)
++count1[code[i] - 'A'];
for (i = 1; i <= 25; i++)
{
strcpy(tmp, org);
init(count2);
for (j = 0; tmp[j] != '\0'; j++)
{
if (tmp[j] + i > 90)
tmp[j] += i - 26;
else
tmp[j] += i;
count2[tmp[j] - 'A']++;
}
if (isEqual(count1, count2))
{
printf("YES\n");
return 0;
}
}
printf("NO\n");
return 0;
}
tianshilei1992 2012-08-04
  • 打赏
  • 举报
回复
[Quote=引用 1 楼 的回复:]

不要排序,用a[26],b[26]分别代表2行字串的每个字符出现的次数。
扫描一遍记录下次数
在b中寻找a里面次数一样的字母 然后算出差值 根据差值来算出下一个字母所对应的值 找不到就进行下一轮循环
全部对应则返回YES 循环走完则返回NO
[/Quote]
我重新写了个程序,但是还是错误呀……不清楚怎么回事……

#include <iostream>
#include <string>

using namespace std;

void init(int* b)
{
int i;
for (i = 0; i < 26; i++)
b[i] = 0;
}

void count(int* b, string tmp)
{
int i;
for (i = 0; tmp[i] != '\0'; i++)
b[tmp[i] - 'A']++;
}

int compare(int* a, int* b)
{
int i;
for (i = 0; i < 26; i++)
if (a[i] != b[i])
return 1;
return 0;
}

int main(void)
{
int a[26], b[26];
int i, j, f = 0;
string code, org, tmp;
cin >> code >> org;
init(a);
for (i = 0; code[i] != '\0'; i++)
a[code[i] - 'A']++;
for (i = 0; i <= 25; i++)
{
tmp = org;
init(b);
for (j = 0; tmp[j] != '\0'; j++)
{
if (tmp[j] + i > 90)
tmp[j] += i - 26;
else
tmp[j] += i;
}
count(b, tmp);
if (compare(a, b) == 0)
{
cout << "YES" << endl;
f = 1;
break;
}
}
if (f == 0)
cout << "NO" << endl;
return 0;
}
MC_LoveX 2012-08-03
  • 打赏
  • 举报
回复
不要排序,用a[26],b[26]分别代表2行字串的每个字符出现的次数。
扫描一遍记录下次数
在b中寻找a里面次数一样的字母 然后算出差值 根据差值来算出下一个字母所对应的值 找不到就进行下一轮循环
全部对应则返回YES 循环走完则返回NO

64,683

社区成员

发帖
与我相关
我的任务
社区描述
C++ 语言相关问题讨论,技术干货分享,前沿动态等
c++ 技术论坛(原bbs)
社区管理员
  • C++ 语言社区
  • encoderlee
  • paschen
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
  1. 请不要发布与C++技术无关的贴子
  2. 请不要发布与技术无关的招聘、广告的帖子
  3. 请尽可能的描述清楚你的问题,如果涉及到代码请尽可能的格式化一下

试试用AI创作助手写篇文章吧