POJ 2159 Ancient Cipher

来源:互联网 发布:淘宝鄂尔多斯旗舰店 编辑:程序博客网 时间:2024/05/16 19:10

她说的应该已经很全面了!!

转载请注明出处:優YoU http://user.qzone.qq.com/289065406/blog/1299062729


PS:本题稍微说一下题意(当时有点发牢骚的感觉,O(∩_∩)O哈哈~)

一种我认为是比较符合现实的解题思路,但是总是Wrong Answer

 

咋看之下确实是被题目忽悠了,一般思路都是先对置换解密,再对乱序解密,但是题目所给出的乱序码只有10个,<2, 1, 5, 4, 3, 7, 6, 10, 9, 8>,输入要求却是不大于100的字符串,这里就显示出了矛盾所在:没有10之后的乱序码根本无法解密!!

 

初看之下这道题目确实是无理取闹,但是从矛盾中同时也给予了我们提示:我们一开始的思路就是错误的!!

 

试想想,实际中对于一段密文,即使我们知道它是使用了凯撒加密(就是置换加密)乱序加密的组合,但是我们却很难得出乱序加密的“顺序”,因为它很可能是随机的!

但是凯撒加密这一环确实可以被破解出来 的,通过循环!因为凯撒加密一开始就脱离不了alphabet!而且对于每一个字母它的置换规则都是一样的,例如A→C,是A往后+2所得,那么B的加密也只能+2,B→D,在alphabet末尾的字母就要卷回alphabet开头。那么通过循环去测试A+i的数字i,也不过是26次而已!

那么乱序加密又如何破解?答案是基本没有办法,除非知道了乱序码。但是可以通过间接手段去验证。下面将叙述。

 

本题其实已经给出了凯撒加密的数字i,就是i=1,这样就省去破解凯撒加密的时间了。

输入密文和猜测的明文后,先破解密文中凯撒加密的部分,那么现在的密文和猜测的明文区别就在于顺序性!

虽然我们不知道乱序码,但是正因为不知道乱序码,我们有更加简单的方法去判定密文和明文是否一致!我们把密文和明文都视为乱序,然后分别对它们的所有字母进行排序!

现在只需要比较排序后的两段文字,就可以判定密文和猜测的明文是否一致了。

 

 

 

正确解题思路

虽然方法更简单,但是正常人很难想到会是这个思路 

不必理会凯撒加密和乱序加密,默认都是不知道解码方法。

那么唯一判断 密文 和 猜测的明文 是否一致的方法就是 把出现频数相同的字母归结为一类(而不必理会组成这一类中的各个字母类型是否一致,但是字母的数量必须一致,例如密文中ABCD都分别出现一次,把他们归为一类,明文中BNUJ也都分别出现一次,把他们也归结为一类,那么这时认为ABCD和BNUJ这两类是等价的;但若密文中ABCD都分别出现一次,而明文中出现一次的只有 KIO三个字母,那么 ABCD和KIO是不等价的),并将出现的次数进行排序,再比较两个频数序列是否相同即可(比较的是频数列,而不是字母列),相同说明可由明文串经变换得出密文串(看这口气好像是说“至于怎么变换出来就不是我们该考虑的问题了,我们管不着!”  )


//Memory   Time //188K      16MS #include<iostream>#include<string>#include<algorithm>using namespace std;int main(void){int i;int cipher[26],clear[26];memset(cipher,0,sizeof(cipher));       //对长度为sizeof(cipher)=int*26=104的连续内存空间cipher全部元素初始化为0memset(clear,0,sizeof(clear));string input;cin>>input;for(i=0;i<input.length();i++){cipher[input[i]-'A']++;}cin>>input;for(i=0;i<input.length();i++){clear[input[i]-'A']++;}sort(cipher,cipher+26);        // 标准库自带排序函数sort(ip_start,ip_end) 对某连续的地址段的对象内容进行升序快排(从小到大),<algorithm>    sort(clear,clear+26);          //亦即sort(ip_start+m,ip_start+n),其中为从ip_start+m开始(包括ip_start+m)对第n到第m个对象进行排序for(i=0;i<26;i++)if(cipher[i]!=clear[i]){cout<<"NO"<<endl;return 0;}cout<<"YES"<<endl;return 0;}


0 0
原创粉丝点击