1. 程式人生 > >1402Vigenère密碼(Noip2012提高組第1題)

1402Vigenère密碼(Noip2012提高組第1題)

http gets 實現 dst 圖片 strong 註意 大小 math.h

維吉尼亞密碼:人們在單一愷撒密碼的基礎上擴展出多表密碼,稱為“維吉尼亞”密碼。該方法最早記錄在吉奧萬·巴蒂斯塔·貝拉索( 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;
}
View Code

敲黑板結論:讀題規劃算法比寫代碼更重要。。。

1402Vigenère密碼(Noip2012提高組第1題)