1402Vigenère密码(Noip2012提高组第1题)
Posted TFLSNOI
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了1402Vigenère密码(Noip2012提高组第1题)相关的知识,希望对你有一定的参考价值。
维吉尼亚密码:人们在单一恺撒密码的基础上扩展出多表密码,称为“维吉尼亚”密码。该方法最早记录在吉奥万·巴蒂斯塔·贝拉索( Giovan Battista Bellaso)于1553年所著的书《吉奥万·巴蒂斯塔·贝拉索先生的密码》(意大利语:La cifra del. Sig. Giovan Battista Bellaso)中。
我大概花了1.5h写出的代码,老同志写代码慢,你们写估计40-50min↓↓↓↓ 缺点:审题不清,代码量大,算法不够严谨,代码运行时间长。。。
1 #include<iostream> 2 #include<cstdio> 3 #include<string> 4 #include<cstring> 5 using namespace std; 6 char a[30][30]; 7 char k[1200],m[1200]; 8 /*step3:密钥和密文来查找明文函数的编写*/ 9 char chazhao(char c1,char c2) 10 { 11 int x,y; 12 //下面循环实现行查找 13 for(int i=1;i<=26;i++) 14 { 15 if(a[i][1]==toupper(c1)) 16 { 17 x=i; 18 break; 19 } 20 } 21 //下面循环实现通过行号和密文结果来找明文 22 for(int i=1;i<=26;i++) 23 { 24 if(a[x][i]==toupper(c2)) 25 { 26 y=i; 27 break; 28 } 29 } 30 //大小写对应 31 if(c2>=‘A‘&&c2<=‘Z‘)return char(‘A‘+y-1); 32 else return char(‘a‘+y-1); 33 } 34 int main() 35 { 36 char c=‘A‘; 37 for(int i=1;i<=26;i++) 38 { 39 for(int j=1;j<=26;j++) 40 { 41 a[i][j]=c; 42 c++; 43 if(c==‘[‘)c=‘A‘; 44 } 45 c++; 46 if(c==‘[‘)c=‘A‘; 47 } 48 /*step1:构造运算规则表,完成之后可以单独测试*/ 49 gets(k); 50 gets(m); 51 int lk=strlen(k),lm=strlen(m); 52 int kk=lk,n=0; 53 while(kk<lm) 54 { 55 k[kk++]=k[n++]; 56 if(n==lk)n=0; 57 } 58 /*step2:让密钥和密文长度一样的放在两个数组中,这样就可以方便下一步一次循环实现*/ 59 for(int i=0;i<lm;i++)cout<<chazhao(k[i],m[i]); 60 return 0; 61 }
网上其他题解↓↓↓↓↓↓↓简短,代码量少。。。算法严谨
本表指 一对密钥与原文可以加密成密文,现在要翻译密文,也就是知道对应的点,也知道了y轴坐标,求x轴坐标。
1.当密文≥密钥时,我们发现数据是依次递增的,则此时ans[i]= miwen[i]-key[j]+‘a‘
2.当密文<密钥时,数据由最右端向左依次递减,此时ans[i]= ‘z‘-(key[j]-miwen[i]-1)
j的意义在后面。
注意这里还有一个易错点,密钥的长度可能小于密文的长度,那么当密钥较短时就要运用循环多次使用此密钥
int j=0;
并且在每次循环后
j++;
if(j==strlen(key))
j=0;
最后通过miwen_x[i]的值将原文的大小写形式恢复原样
这样就解决此问题了
本题总思路:
1.读入密钥、密文并转换成小写(大写也可),同时记录密文的大小写情况
2. 运用算法算出原文
3.通过大小写情况恢复原文的大小写
#include<stdio.h> #include<stdlib.h> #include<string.h> #include<math.h> int change(int i)//大小写转换 { return (i>=‘A‘&&i<=‘Z‘)?i+‘a‘-‘A‘:i; } int main() { char key[120]; char miwen[1200]; int miwen_x[1200];//密文大小写 1小写 2大写 scanf("%s %s",key,miwen); int len=strlen(key); for(int i=0;i<=len-1;i++) key[i]=change(key[i]); for(int i=0;i<=strlen(miwen)-1;i++) { if(miwen[i]>=‘A‘&&miwen[i]<=‘Z‘) miwen_x[i]=2; else miwen_x[i]=1; miwen[i]=change(miwen[i]); } char ans[1200]; int j=0; for(int i=0;i<=strlen(miwen)-1;i++) { if(miwen[i]>=key[j]) ans[i]=miwen[i]-key[j]+‘a‘; else ans[i]=‘z‘-(key[j]-miwen[i]-1); if(miwen_x[i]==2) ans[i]=ans[i]-(‘a‘-‘A‘); j++; if(j==len) j=0; } ans[strlen(miwen)]=0; printf("%s",ans); return 0; }
敲黑板结论:读题规划算法比写代码更重要。。。
以上是关于1402Vigenère密码(Noip2012提高组第1题)的主要内容,如果未能解决你的问题,请参考以下文章