zoukankan      html  css  js  c++  java
  • Playfair 加密

    题目真的好长但是意思很简单

    89.加密 (15分)
    C时间限制:3 毫秒 | C内存限制:3000 Kb
    题目内容:
    一种Playfair密码变种加密方法如下:首先选择一个密钥单词(称为pair)(字母不重复,且都为小写字母),然后与字母表中
    其他字母一起填入至一个5x5的方阵中,填入方法如下:
    1.首先按行填入密钥串。
    2.紧接其后,按字母序按行填入不在密钥串中的字母。
    3.由于方阵中只有25个位置,最后剩下的那个字母则不需变换。
    如果密钥为youandme,则该方阵如下:
    y o u a n
    d m e b c
    f g h i j
    k l p q r
    s t v w x
    在加密一对字母时,如am,在方阵中找到以这两个字母为顶点的矩形:
    o u a
    m e b

    这对字母的加密字母为该矩形的另一对顶点,如本例中为ob。
    请设计程序,使用上述方法对输入串进行加密,并输出加密后的串。
    另外有如下规定:
    1、一对一对取字母,如果最后只剩下一个字母,则不变换,直接放入加密串中;
    2、如果一对字母中的两个字母相同,则不变换,直接放入加密串中;
    3、如果一对字母中有一个字母不在正方形中,则不变换,直接放入加密串中;
    4、如果字母对出现在方阵中的同一行或同一列,如df或hi,则只需简单对调这两个字母,即变换为fd或ih;
    5、如果在正方形中能够找到以字母对为顶点的矩形,假如字母对为am,则该矩形的另一对顶点字母中,与a同行的字母应在前
    面,在上例中应是ob;同样若待变换的字母对为ta,则变换后的字母对应为wo;
    6、本程序中输入串均为小写字母,并不含标点、空格或其它字符。
    解密方法与加密相同,即对加密后的字符串再加密,将得到原始串。
    输入描述
    从控制台输入两行字符串,第一行为密钥单词(长度小于等于25,字母不重复,且都为小写字母),第二行为待加密字符串(长度
    小于等于50),两行字符串末尾都有一个回车换行符,并且两行字符串均为小写字母,不含其它字符。

    输出描述
    在标准输出上输出加密后的字符串。

    输入样例
    youandme
    welcometohangzhou

    输出样例
    vbrmmomvugnagzguu

    样例解释:

    y  o u  a n
    d m e  b c
    f  g  h  i   j
    k  l  p  q  r
    s t  v  w x

    welcometohangzhou

    (一对一对找)找到对应的矩阵,输出另一个对角上面的字母,

    如果其中一个字母不在矩阵中,原样输出

    如果在同行或者同列,位置对调

    如果剩最后一个字母,原样输出

    we --> vb   lc-->rm  om -->mo  et-->mv  oh-->ug     an-->na    gz-->gz   ho-->gu   u-->u

    #include <stdio.h>
    #include <string.h>
    char s1[26];
    char str[55];   
    char s[5][5];  //加密矩阵 
    int a[27];
    typedef struct{
        int x, y; //记录字母的横纵坐标 
    }P;
    P p[27]; 
    int main(){
        scanf("%s%s", s1, str);
        memset(a, 0, sizeof a);
        int i = 0; 
        while(s1[i]){
            int d = s1[i] - 'a';
            a[d] = 1;
            i++;
        }
        int k = 0, len = strlen(s1);
        int f = 0;
        for(int i = 0; i < 5; i++){
            for(int j = 0; j < 5; j++){
                if(k < len){
                    s[i][j] = s1[k];
                    k++;
                }else{
                    while(a[f] && f <= 25){ //循环结束时 a[f] = 0 
                        f++;
                    }
                    char c = f + 'a';
                    s[i][j] = c;
                    f++;
                }
            }
        }
        
        memset(a, 0, sizeof a);
        for(int i = 0; i < 5; i++){
            for(int j = 0; j < 5; j++){
                int d = s[i][j] - 'a';
                p[d].x = i; p[d].y = j;
                a[d] = 1;//判断是否出现过 
            }
        }
        
        
        i = 0; len = strlen(str);
        while(str[i]){
            if(i == len - 1){//最后一个单着
                printf("%c", str[i]); 
                i++;
            }else{
                //找到横纵坐标
                int d1 = str[i] - 'a';
                int d2 = str[i+1] - 'a';
                if(a[d1] && a[d2]){//就是都在加密矩阵中 
                    int x1 = p[d1].x, y1 = p[d1].y;
                    int x2 = p[d2].x, y2 = p[d2].y;
                    //如果在同一列
                    if(y1 == y2){
                        printf("%c%c", str[i+1], str[i]);
                    } else{
                        printf("%c%c", s[x1][y2], s[x2][y1]);
                    }
                }else{
                    printf("%c%c", str[i], str[i+1]);
                } 
                i += 2;
            }
        }
        return 0;
    } 
    View Code
  • 相关阅读:
    一个长串由一个字串循环构成
    区间边界 张贴海报的可见性
    summary
    分区本质 从磁盘物理层面优化查询 分区操作的锁表
    全局变量在反汇编中是怎么体现的
    MathType怎么打定积分竖线
    定积分换元法洛必达法则求极限
    静态链表的插入和删除
    Git恢复之前版本的两种方法reset、revert
    服务去耦合
  • 原文地址:https://www.cnblogs.com/DDiamondd/p/10744250.html
Copyright © 2011-2022 走看看