poj 2159

来源:互联网 发布:电竞鼠标 知乎 编辑:程序博客网 时间:2024/06/16 03:20
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是不等价的),并将出现的次数进行排序,再比较两个频数序列是否相同即可(比较的是频数列,而不是字母列),相同说明可由明文串经变换得出密文串(看这口气好像是说“至于怎么变换出来就不是我们该考虑的问题了,我们管不着!”  )
“substitution cipher (置换密码):
Substitution cipher changes all occurrences of each letter to some other letter. Substitutes for all letters must be different. For some letters substitute letter may coincide with the original letter. For example, applying substitution cipher that changes all letters from 'A' to 'Y' to the next ones in the alphabet, and changes 'Z' to 'A', to the message "VICTORIOUS" one gets the message "WJDUPSJPVT".
“移位”只是置换密码的一种,只要满足“Substitutes for all letters must be different.”就是置换了,比如
A->B
C->H
Z->D
对于这道题,input:
AAABB
CCCEE
应输出
YES
所以明文与密文的“字母频率的数组”应该是一样的,即明文中某字母出现8次,密文中也必须有某个字母出现8次。
所以字母种类,字母频率同时相等时,即被破解。
permutation cipher(排列密码):
Permutation cipher applies some permutation to the letters of the message. For example, applying the permutation <2, 1, 5, 4, 3, 7, 6, 10, 9, 8> to the message "VICTORIOUS" one gets the message "IVOTCIRSUO".
明文随机排列,所以字母种类和频率都不变。

对于这道题,排列密码考虑和不考虑对解题无影响!”


#include<stdio.h>#include<string.h>#include<stdlib.h>int cmp(const void *a,const void *b){return *(int*)a-*(int*)b;}int main(){char s1[200],s2[200];int a[100],b[100],c[100],d[100],k1,k2,i;scanf("%s%s",s1,s2);memset(a,0,sizeof(a));memset(b,0,sizeof(b));for(i=0;s1[i]!='\0';i++){if(s1[i]>='A'&&s1[i]<='Z')a[s1[i]-'A']++;}for(i=0;s2[i]!='\0';i++){if(s2[i]>='A'&&s2[i]<='Z')    b[s2[i]-'A']++;}k1=k2=0;for(i=0;i<26;i++){    if(a[i]!=0)c[k1++]=a[i];if(b[i]!=0)d[k2++]=b[i];}qsort(c,k1,sizeof(c[0]),cmp);qsort(d,k2,sizeof(c[0]),cmp);if(k1!=k2)printf("NO\n");else{      for(i=0;i<k1;i++)  if(c[i]!=d[i])  break;if(i==k1)printf("YES\n");elseprintf("NO\n");}return 0;}


0 0
原创粉丝点击