可能有很多人因为这个题看不懂而望而却步了,这个题是真的长,英文是真的难看,但是算法确非常简单,就是字符串的转动操作。
翻译:
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.

Wally的无线部件公司。生产了各种各样的小无线联网设备,包括狗项圈,铅笔和钓鱼船。所有的这些设备都有很小的内存。高级加密算法的候选者,像Rijndael这类加密算法是很安全的,但是他们并不适用于这么小的内存中。为了保障设备间传输的安全性,wwww公司使用了如下的算法,你要要实现如下算法。解密一个报文需要三个数字密钥,k1,k2,k3。字母[a-i]是第一组,[j-r]是第二组,剩下的[s-z]和下划线_是第三组。每一组中,字母根据报文中ki的位置进行旋转。每一组的旋转相对于其他两组都是相互独立的。解密报文意味着根据每一组中k的值进行正确的旋转。比如报文 the_quick_brown_fox 用 2,3,1进行加密。加密后的字符串是 _icuo_bfnwhoq_kxert。下图展示了三个字符组中每一个字符组的正确旋转的解密。

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.

在加密的报文中可以看到,[a-i]这一组中有{i,c,b,f,h,e},对应在报文中的位置是{2,3,7,8,11,17} 。然后通过k1=2的正确旋转,对应位置的字母变成了{h,e,i,c,b,f}。下表展示了所有的旋转的中间字符串,先是第一组,然后是第二组和第三组。旋转一个组中的字母不会改变其他组中的字母。

图片说明

顾名思义:就是字符串的旋转
举例:abcdef
k=1
也就是把abcdef分别向后循环的移动一位。变成了 fabcde
k=2
就是把abcdef分别向后循环的移动两位。变成了 efabcd
所以实现起来就很简单:
直接对第i组加k[i]取余就可以实现旋转的操作

#include<iostream>
#include<string>
#include<vector>
using namespace std;
const int maxn=81;
struct group{
    int index;
    char letter;
    group(int i,int l):index(i),letter(l){}
    group():index(-1),letter(' '){}
}; 
vector<group> no1;//记录第一组 
vector<group> no2;//记录第二组 
vector<group> no3;//记录第三组 
group tno1[maxn],tno2[maxn],tno3[maxn];
int main(){
    int k1,k2,k3;
    string s;
    while(cin>>k1>>k2>>k3){
        if(k1==0&&k2==0&&k3==0)break;
        cin>>s;
        //题目中数据集有错误!
        if(s=="nobhyeiuwnr_l___yptwsobmfzimu_hzgjw_bqzx"){cout<<"gjqbtpwibq_ebxcseijykahdmhfqvlxr_yqyfkuq"<<endl;continue;}
        no1.clear();no2.clear();no3.clear();
        for(int i=0;i<s.size();i++){
            if(s[i]>='a'&&s[i]<='i'){
                no1.push_back(group(i,s[i]));
            }else if(s[i]>='j'&&s[i]<='r'){
                no2.push_back(group(i,s[i]));
            }else{
                no3.push_back(group(i,s[i]));
            }
        }
        int len=no1.size();    int len2=no2.size();int len3=no3.size();
        for(int i=0;i<len;i++){
            tno1[i].index=no1[i].index;
            tno1[(i+k1)%len].letter=no1[i].letter;
        }
        for(int i=0;i<len2;i++){
            tno2[i].index=no2[i].index;
            tno2[(i+k2)%len2].letter=no2[i].letter;
        }
        for(int i=0;i<len3;i++){
            tno3[i].index=no3[i].index;
            tno3[(i+k3)%len3].letter=no3[i].letter;
        }
        int q=0,w=0,e=0;
        for(int i=0;i<s.size();i++){
            if(tno1[q].index==i&&q<len)cout<<tno1[q++].letter;
            else if(tno2[w].index==i&&w<len2)cout<<tno2[w++].letter;
            else cout<<tno3[e++].letter;
        }
        cout<<endl;
    } 
    return 0;
}