1107:W‘s Cipher(已翻译题目)

描述

Weird Wally's Wireless Widgets, Inc. manufactures an eclectic assortment of small, wireless, network capable devices, ranging from dog collars, to pencils, to fishing bobbers. All these devices have very small memories. Encryption algorithms like Rijndael, the candidate for the Advanced Encryption Standard (AES) are demonstrably secure but they don't fit in such a tiny memory. In order to provide some security for transmissions to and from the devices, WWWW uses the following algorithm, which you are to implement.
Encrypting a message requires three integer keys, k1, k2, and k3. The letters [a-i] form one group, [j-r] a second group, and everything else ([s-z] and underscore) the third group. Within each group the letters are rotated left by ki positions in the message. Each group is rotated independently of the other two. Decrypting the message means doing a right rotation by ki positions within each group.
Consider the message the_quick_brown_fox encrypted with ki values of 2, 3 and 1. The encrypted string is _icuo_bfnwhoq_kxert. The figure below shows the decrypting right rotations for one character in each of the three character groups.


Looking at all the letters in the group [a-i] we see {i,c,b,f,h,e} appear at positions {2,3,7,8,11,17} within the encrypted message. After a right rotation of k1=2, these positions contain the letters {h,e,i,c,b,f}. The table below shows the intermediate strings that come from doing all the rotations in the first group, then all rotations in the second group, then all the rotations in the third group. Rotating letters in one group will not change any letters in any of the other groups.


All input strings contain only lowercase letters and underscores(_). Each string will be at most 80 characters long. The ki are all positive integers in the range 1-100.

怪人沃利的无线部件公司制造各种小型,无线,网络能力的设备,从狗项圈,铅笔,钓鱼浮标。所有这些设备都有非常小的存储器。像 Rijndael 这样的加密算法,作为高级加密标准(aES)的候选者,显然是安全的,但它们不适合如此小的内存。为了为设备之间的传输提供某种安全性,WWWW 使用以下算法,您将实现这些算法。对消息进行加密需要三个整数密钥: k1、 k2和 k3。字母[ a-i ]组成一个组,[ j-r ]组成第二个组,其他的([ s-z ]和下划线)组成第三个组。在每个组中,字母按照消息中的 ki 位置旋转。每组独立于另外两组旋转。解密消息意味着按照每个组中的 ki 位置进行正确的旋转。请考虑使用 ki 值2、3和1加密的 _ fast _ brown _ fox 消息。加密的字符串是 _ icuo _ bfnwhoq _ kxert。下图显示了三个字符组中每个字符的右旋转解密。查看组[ a-i ]中的所有字母,我们看到{ i,c,b,f,h,e }出现在加密消息中的位置{2,3,7,8,11,17}。在 k1 = 2的右旋转之后,这些位置包含字母{ h,e,i,c,b,f }。下面的表格显示了中间字符串,它们来自于第一组的所有旋转,然后是第二组的所有旋转,然后是第三组的所有旋转。一个组中的旋转字母不会改变其他组中的任何字母。所有输入字符串只包含小写字母和下划线(_)。每个字符串最多只有80个字符。在1-100范围内,所有的 ki 都是正整数。

输入
Input consists of information for one or more encrypted messages. Each problem begins with one line containing k1, k2, and k3 followed by a line containing the encrypted message. The end of the input is signalled by a line with all key values of 0.

输入由一条或多条加密消息的信息组成。每个问题都从一行开始,其中包含 k1、 k2和 k3,然后是一行,其中包含加密的消息。输入的结束用一行代码表示,所有键值都为0。

输出
For each encrypted message, the output is a single line containing the decrypted string.

对于每个加密的消息,输出是包含解密字符串的单行。

样例输入
2 3 1
_icuo_bfnwhoq_kxert
1 1 1
bcalmkyzx
3 7 4
wcb_mxfep_dorul_eov_qtkrhe_ozany_dgtoh_u_eji
2 4 3
cjvdksaltbmu
0 0 0

样例输出
the_quick_brown_fox
abcklmxyz
the_quick_brown_fox_jumped_over_the_lazy_dog
ajsbktcludmv

来源
Mid-Central USA 2001


分析

解密的过程其实就是信息中属于每组的字符,都循环的向右移ki个位置。用字符数组s[]来存储加密信息,

s1[]来保存解密后的信息。统计每组字符的个数numi,如果不为0,就将他们右移ki%numi个位置,然后

存入s1[]数组中,最后输出s1[]。


代码
#include<iostream>
#include<algorithm>
#include<cstdio>
#include<cstring>
using namespace std;
 
char s[110],s1[110];
int num[110];
 
void Rotate(int i,int k,int len)
{
    int no = 0,j = i;
    while(no != k)
    {
        j++;
        if(j > len-1)
            j = 0;
        if(num[j] == num[i])
            no++;
    }
    s1[j] = s[i];
 
}
 
int main()
{
    int k1,k2,k3,num1,num2,num3;
    while(~scanf("%d%d%d",&k1,&k2,&k3) && (k1||k2||k3))
    {
        scanf("%s",s);
        int len = strlen(s);
        memset(num,0,sizeof(num));
        memset(s1,0,sizeof(s1));
        num1 = num2 = num3 = 0;
        for(int i = 0; i < len; ++i)
        {
            if(s[i]>='a' && s[i]<='i')
            {
                num1++;
                num[i] = 1;
            }
            else if(s[i]>='j' && s[i]<='r')
            {
                num2++;
                num[i] = 2;
            }
            else
            {
                num3++;
                num[i] = 3;
            }
        }
 
        for(int i = 0; i < len; ++i)
        {
            if(num[i] == 1)
            {
                if(num1 != 0)
                    Rotate(i,k1%num1,len);
            }
            else if(num[i] == 2)
            {
                if(num2 != 0)
                    Rotate(i,k2%num2,len);
            }
            else
            {
                if(num3 != 0)
                    Rotate(i,k3%num3,len);
            }
        }
        s1[len] = '\0';
        printf("%s\n",s1);
    }
 
    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值