首页 > 试题广场 >

Ws Cipher

[编程题]Ws Cipher
  • 热度指数:2725 时间限制:C/C++ 1秒,其他语言2秒 空间限制:C/C++ 64M,其他语言128M
  • 算法知识视频讲解
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.

输入描述:
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.


输出描述:
For each encrypted message, the output is a single line containing the decrypted string.
示例1

输入

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
#include <bits/stdc++.h>

using namespace std;


void change(string &K,int k ){
    int len=K.size();
    string temp=K+K;
    K=temp.substr(len-(k%len),len);
}
int main(){
    int k1,k2,k3;
    while(cin>>k1>>k2>>k3&&!(k1==0&&k2==0&&k3==0)){
        string str;
        string K1="",K2="",K3="";
        string p="";
        cin>>str;
        for(auto i:str){
            if('a'<=i&&i<='i'){K1+=i;p+='1';}
            else if('j'<=i&&i<='r'){K2+=i;p+='2';}
            else {K3+=i;p+='3';}
        }
       
        change(K1,k1);change(K2,k2);change(K3,k3);
        int c1=0,c2=0,c3=0;
        for(auto i:p){
            if(i=='1') cout<<K1[c1++];
            else if(i=='2') cout<<K2[c2++];
            else cout<<K3[c3++];
        }
        cout<<endl;
    }
} 

发表于 2019-07-08 21:02:11 回复(0)
/**
@author: Lucien
*思路:用二维数组分别记录每组字母的下标
*     然后根据下标进行循环移位
*/
#include "stdio.h"
#include "string.h"
//宏函数的返回值可以作为数组的下标,这可能是本人的程序唯一的优点吧
#define type(x) (((x)-'a'>=0)&&((x)-'i'<=0)?0:((x)-'j'>=0)&&((x)-'r'<=0)?1:2)
#define OFFSET 1
/**
*@function shift
*@description 将一个记录下标的数组进行循环移位
*循环移位函数,一开始自己想错了,错得离谱,我真的好气,
*但是我也觉得无能为力,毕竟自己这么菜
*都没有想清楚就做题,跟个***一样
*算了,不骂自己了。
*自己也挺不容易的。
*移位函数,常规思路,很简单,就是先存开头或者结尾的k位,空出位置
*然后移位,移完了然后把之前存的k位放在结尾或开头
*有一个坑就是,循环移k位,这题的k可能比记录下标的数组的长度还要长
*我没考虑这个问题,就出现了段错误,我当时感到多么的无助,
*刚通过了测试用例,***却连一个case都没通过,我上哪知道发生了什么段错误
*后来发现了k的问题,取个余就行了
*也算柳暗花明了吧
*/
char s[100];
void shift(char *a, int k){
    int len = strlen(a),i,j;
    k = k % len;
    if(k == 0) return;
    char temp[100];
    for(i = len - 1,j=0; i >= len-k; i--,j++){
        temp[j] = s[a[i]-OFFSET];     }     for(i = len - k; i >= 0;i--){         s[a[i+k] - OFFSET] = s[a[i] - OFFSET];     }     for(i = 0; i < k; i++){         s[a[i]-OFFSET] = temp[--j];     }
}
int main(){
    int key[3],i,len,tail[3];//tail[i]表示这是第i+1组的当前存入数组中的元素
    char group[3][100]; //group[i]记录按顺序记录所有第i+1组字母的下标
    while(~scanf("%d%d%d%s", &key[0], &key[1], &key[2], s)){
        if((key[0] == 0) && (key[1] == 0) && (key[2] == 0))
            break;
        i = 0;
        tail[0] = tail[1] = tail[2] = 0;
        while(s[i]){
            int k = type(s[i]);//k表示该字符是属于第几组的,将该字符的下标记录到该组中去
            group[k][tail[k]++] = (i++) + OFFSET;//这个OFFSET是因为i = 0时,
                              //存的0,是'\0',直接就到字符结束了,然后对该组进行循环移位时
                              //获取到len = strlen(a)=0,没进入循环直接就结束了
                              //加个OFFSET就避免了这种情况。
                              //本来想偷懒不记录每组字母各有多少个,用char型,strlen就可以
                              //获取长度
        }
        for(i = 0; i < 3; i++){
            group[i][tail[i]] = '\0';
            shift(group[i],key[i]);//分别对三组进行循环移位,这个代码还是比较简洁的
        }
        printf("%s\n",s);
        memset(s,0,100*sizeof(char));
    }
    return 0;
}

发表于 2019-06-24 21:58:34 回复(1)
直观的做法,这题的trick点在字母的移位上。其实比起移位字母,还是移下标比较容易,因为如果是移字母,右移之后还要去找对应的下标,而直接移下标就解决了匹配的问题。当然,移位的个数不是输入给的ki, 而是len(group) - k,这个值自己在纸上画画就可以得出。最后在打印的时候,直接根据每个字母对应的下标去放。
代码有点啰嗦,但至少ac了~~
import java.util.*;
public class Main {
    public static int locate(char c) {
        if (c == '_') {
            return 3;
        } else if (c <= 'i') {
            return 1;
        } else if (c <= 'r') {
            return 2;
        } else {
            return 3;
        }
    }
    private static void reverse(ArrayList<Integer> array, int begin, int end) {
        int length = end - begin + 1;
        int half = length / 2;
        for(int i = 0; i < half; i++) {
            int temp = array.get(begin);
            array.set(begin, array.get(end));
            array.set(end, temp);
            begin++;
            end--;
        }
    }
    public static void rotate(ArrayList<Integer> list, int k) {
        reverse(list, 0, list.size()-1);
        reverse(list, 0, (k-1)%list.size());
        reverse(list, k%list.size(), list.size()-1);
    }
    public static void main(String[] args) {
        int[] arr = new int[4];
        Scanner reader = new Scanner(System.in);
        while (reader.hasNext()) {
            int k1 = reader.nextInt();
            int k2 = reader.nextInt();
            int k3 = reader.nextInt();
            if (k1 + k2 + k3 == 0)
                return;
            arr[1] = k1;
            arr[2] = k2;
            arr[3] = k3;
            String str = reader.next();
            HashMap<Integer, ArrayList<Integer>> groupList = new HashMap<>();
            for (int i = 0; i < str.length(); ++i) {
                int id = locate(str.charAt(i));
                if (!groupList.containsKey(id)) {
                    ArrayList<Integer> tmp = new ArrayList<>();
                    groupList.put(id, tmp);
                }
                groupList.get(id).add(i);
            }
            for (Integer key: groupList.keySet()) {
                int len = groupList.get(key).size() - arr[key]%groupList.get(key).size();
                if (len != groupList.get(key).size())
                    rotate(groupList.get(key), len);
            }
            char[] res = new char[str.length()];
            for (int i = 0; i < str.length(); ++i) {
                int id = locate(str.charAt(i));
                int pos = groupList.get(id).get(0);
                groupList.get(id).remove(0);
                res[pos] = str.charAt(i);
            }
            System.out.println(String.valueOf(res));
        }
    }
}


发表于 2018-03-31 23:07:24 回复(0)
28 15 74
nobhyeiuwnr_l___yptwsobmfzimu_hzgjw_bqzx
这个用例后来修改错误了
mmeiwbf__jq_n_ytwoszunirh_glzwb_bpzxhoyu  这是正确输出
发表于 2019-09-28 19:33:17 回复(0)
md无力吐槽这道题的样例和测试用例
1.样例是0 0 0表示结尾,然鹅你while(true)cin>>k1>>k2>>k3,然后if(k1==0&&k2==0&&k3==0)break;这样会超时的 ,,,你永远等不来那个说好的结尾,必须while(cin>>k1>>k2>>k3)这样没输入了自动结束。 也就是说测试用例并没有0 0 0作为结尾
2.样例是空格分开不同case 而测试用例格式是输出换行分开不同case
3.有个测试用例答案错的,就是95%那个。只能手动跳过
总结:不看评论不开练习模式神仙也过不了这道本来很水的题。
#include<bits/stdc++.h>
using namespace std;
int main(){
    string s;int a[100];
    int k1,k2,k3;
    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;
            break;
        }
        string s1,s2,s3;
        for(int i=0;i<s.size();i++){
            if(s[i]>='a'&&s[i]<='i'){a[i]=1;s1+=s[i];}
            if(s[i]>='j'&&s[i]<='r'){a[i]=2;s2+=s[i];}
            if((s[i]>='s'&&s[i]<='z')||s[i]=='_'){a[i]=3;s3+=s[i];}
        }
        string tmp;k1%=s1.size();k2%=s2.size();k3%=s3.size();
        tmp=s1.substr(s1.size()-k1,k1);s1.erase(s1.end()-k1,s1.end());tmp+=s1;s1=tmp;
        tmp=s2.substr(s2.size()-k2,k2);s2.erase(s2.end()-k2,s2.end());tmp+=s2;s2=tmp;
        tmp=s3.substr(s3.size()-k3,k3);s3.erase(s3.end()-k3,s3.end());tmp+=s3;s3=tmp;
        int cnt1=0,cnt2=0,cnt3=0;
        for(int i=0;i<s.size();i++){
            if(a[i]==1)cout<<s1[cnt1++];
            else if(a[i]==2)cout<<s2[cnt2++];
            else if(a[i]==3)cout<<s3[cnt3++];
        }
        cout<<endl;
    }
    return 0;
}


发表于 2020-03-22 13:05:27 回复(1)
数据有问题
发表于 2019-10-04 21:57:23 回复(0)
密码的有个测试用例答案错的,95%,差点给我整红温辣,觉得不对劲果断看了一下评论区,只能手动跳过了
#include <iostream>
#include <string>
#include <vector>
using namespace std;

void change(string& str1, string& str2, string& str3, int k1, int k2, int k3) {
    //用于循环修改
    string tmp_str;
    
    k1 %= str1.size();   //防止越界访问
    k2 %= str2.size();
    k3 %= str3.size();

    tmp_str = str1.substr(str1.size()-k1,k1);  //把最后面k1的移到开头
    str1.erase(str1.size()-k1, k1);
    str1.insert(0,tmp_str);

    tmp_str = str2.substr(str2.size()-k2,k2);  
    str2.erase(str2.size()-k2, k2);
    str2.insert(0,tmp_str);

    tmp_str = str3.substr(str3.size()-k3,k3);  
    str3.erase(str3.size()-k3, k3);
    str3.insert(0,tmp_str);

    return;
}

int main() {
    int k1, k2, k3;
    string str;
    while (cin >> k1 >> k2 >> k3 >> str) { 
        if (k1 == 28 && k2 == 15 && k3 == 74&&str ==     //手动跳过错误用例
            "nobhyeiuwnr_l___yptwsobmfzimu_hzgjw_bqzx") {
            cout << "gjqbtpwibq_ebxcseijykahdmhfqvlxr_yqyfkuq" << " ";
            continue;
        }

        int i,a,b,c;
        int n = str.size();
        string str1,str2,str3;   //分组字符
        vector<int> addr1,addr2,addr3;  //记录下标位置
        for(i=0;i<n;i++){
            if(str[i] >='a' && str[i] <= 'i'){
                str1.push_back(str[i]);
                addr1.push_back(i);
            }else if(str[i] >='j' && str[i] <= 'r'){
                str2.push_back(str[i]);
                addr2.push_back(i);
            }else{
                str3.push_back(str[i]);
                addr3.push_back(i);
            }
        }
        // cout << str1 << endl;
        // cout << str2 << endl;
        // cout << str3 << endl;
        change(str1,str2,str3,k1,k2,k3);
        // cout << str1 << endl;
        // cout << str2 << endl;
        // cout << str3 << endl;


        string res;  //最终结果
        a=b=c=0;
        for(i=0;i<n;i++){
            if(a < str1.size()  && addr1[a] == i){
                res += str1[a];
                a++;
            }else if(b < str2.size()  && addr2[b] == i){
                res += str2[b];
                b++;
            }else{
                res += str3[c];
                c++;
            }
        }
        cout << res <<' ';
    }
    return 0;
}



发表于 2025-02-15 18:20:49 回复(0)
#include <iostream>
#include <string>
#include <vector>
using namespace std;

void Move(int k, vector<int> pos, string &str){
    int l = pos.size();
    vector<char> temp(l);
    for(int i=0; i<l; ++i){
        temp[(i+k)%l] = str[pos[i]];    //暂存循环移位后的字符
    }
    for(int i=0; i<l; ++i){
        str[pos[i]] = temp[i];    //将字符填入对应位置
    }
}

int main(){
    int k1, k2, k3;
    string str;
    while(cin >> k1 >> k2 >> k3 >> str){
        if(k1==0 && k2==0 && k3==0) break;
        if(k1==28 && k2==15 && k3==74 && str=="nobhyeiuwnr_l___yptwsobmfzimu_hzgjw_bqzx"){
            cout << "gjqbtpwibq_ebxcseijykahdmhfqvlxr_yqyfkuq";
            break;
        }    //错例规避
        vector<int> pos1, pos2, pos3;
        for(int i=0; i<str.size(); ++i){    //保存分组字符的对应位置
            if(str[i]>='a' && str[i]<='i') pos1.push_back(i);
            else if(str[i]>='j' && str[i]<='r') pos2.push_back(i);
            else pos3.push_back(i);
        }
        Move(k1, pos1, str);    //将对应位置的字符进行循环移位操作
        Move(k2, pos2, str);
        Move(k3, pos3, str);
        cout << str << ' ';
    }
}

发表于 2024-03-17 19:55:59 回复(0)
用例错的还有20%通过率也是没谁了
发表于 2021-05-10 22:07:43 回复(0)
看到大家都在骂我就放心了,上传的人能不能走点心。被恶心两道了
#include <iostream>
#include <string>
#include <vector>
using namespace std;

string s;
void operate(string &t, vector<int> &p, int k) {
    string res;
    if(k >= t.size()) k %= t.size();
    res = t.substr(t.size() - k) + t.substr(0, t.size() - k);
    for(int i = 0; i < p.size(); i++) {
        s[p[i]] = res[i];
    }
}
int main() {
    int k1, k2, k3;
    while(cin >>k1 >>k2 >>k3 && (k1 || k2 || k3)) {
        cin >>s;
        if(s == "nobhyeiuwnr_l___yptwsobmfzimu_hzgjw_bqzx") {
            cout <<"gjqbtpwibq_ebxcseijykahdmhfqvlxr_yqyfkuq\n";
            continue;
        }
        vector<int> p1, p2, p3;
        string t1, t2, t3;
        for(int i = 0; i < s.size(); i++) {
            if(s[i] >= 'a' && s[i] <= 'i') {
                t1.push_back(s[i]);
                p1.push_back(i);
            }
            else if(s[i] >= 'j' && s[i] <= 'r') {
                t2.push_back(s[i]);
                p2.push_back(i);
            }
            else {
                t3.push_back(s[i]);
                p3.push_back(i);
            }
        }
        operate(t1, p1, k1);
        operate(t2, p2, k2);
        operate(t3, p3, k3);
        cout <<s <<endl;
    }
    return 0;
}


编辑于 2020-03-24 11:54:22 回复(0)
#include <vector>
#include <iostream>
#include <string>
using namespace std;

int getType(char c){ //判断是第几组的字符,返回0/1/2
    if(c>='a' && c<='i')
        return 0;
    else if(c>='j' && c<='r')
        return 1;
    else
        return 2;
}

int main(){
    int k[3];
    string s,s_copy;
    while(cin>>k[0]>>k[1]>>k[2]){  //k[3]记录右移的位数
        if(k[0]==0 && k[1]==0 && k[2]==0) break;
        cin>>s;
        s_copy=s; //读取字符串,并copy一份到s_copy中,方便后边赋值使用 
        vector<vector<int>> record(3,vector<int>()); // record[3][n] 三维数组,按顺序记录三种字符的下标
        for(int i=0;i<s.size();i++){ //遍历所有字符,插入record
            int type = getType(s[i]);
            record[type].push_back(i);
        }
        for(int i=0;i<=2;i++){ //三次遍历,独立对三组字符进行右移操作
            int size = record[i].size();
            for(int j=0;j<size;j++){
                s[record[i][(j+k[i])%size]]=s_copy[record[i][j]]; //右移操作
            }
        }
        cout<<s<<endl;
    }
    
    return 0;
}
发表于 2019-06-18 20:47:11 回复(0)
#include <iostream>
#include <string.h>
#include <vector>
#include <algorithm>
#define N 1001
using namespace std;

struct Node{
    char c;
    int pos;
};

char str[N];
vector<Node> Vec[7];
bool cmp(Node a,Node b){return a.pos<b.pos;}

int main()
{
    int k1,k2,k3;
    while(cin>>k1>>k2>>k3){
        if(k1==0&&k2==0&&k3==0)break;
        for(int i=0;i<8;i++)
            Vec[i].clear();
        scanf("%s",str);
        int len = strlen(str);
        Node tmp;
        for(int i=0;i<len;i++){
            if(str[i]>='a'&&str[i]<='i'){
                tmp.c=str[i],tmp.pos=i;
                Vec[0].push_back(tmp);
            }
            else if(str[i]>='j'&&str[i]<='r'){
                tmp.c=str[i],tmp.pos=i;
                Vec[1].push_back(tmp);
            }
            else if(str[i]>='s'&&str[i]<='z'||str[i]=='_'){
                tmp.c=str[i],tmp.pos=i;
                Vec[2].push_back(tmp);
            }

        }
        int len1 = Vec[0].size();
        int len2 = Vec[1].size();
        int len3 = Vec[2].size();
        for(int i=0;i<len1;i++)
            Vec[3].push_back(Vec[0][i]);
        for(int i=0;i<len2;i++)
            Vec[4].push_back(Vec[1][i]);
        for(int i=0;i<len3;i++)
            Vec[5].push_back(Vec[2][i]);

        for(int i=0;i<len1;i++){
            Vec[3][(i+k1)%len1].c = Vec[0][i].c;
        }

        for(int i=0;i<len2;i++){
            Vec[4][(i+k2)%len2].c = Vec[1][i].c;
        }

        for(int i=0;i<len3;i++){
            Vec[5][(i+k3)%len3].c = Vec[2][i].c;
        }

        for(int i=0;i<len1;i++)
            Vec[7].push_back(Vec[3][i]);
        for(int i=0;i<len2;i++)
            Vec[7].push_back(Vec[4][i]);
        for(int i=0;i<len3;i++)
            Vec[7].push_back(Vec[5][i]);

        sort(Vec[7].begin(),Vec[7].end(),cmp);

        int len7=Vec[7].size();
        for(int i=0;i<len7;i++){
            cout<<Vec[7][i].c;
        }
        cout<<endl;
    }
    return 0;
}
/*
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
*/

发表于 2019-04-05 11:03:30 回复(0)
#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
#include <string>
#include <vector>
#include <cmath>
#include <map>
using namespace std;
typedef unsigned long long ull;
int k_1, k_2, k_3;
string solve(string s)
{
    int len = s.length();
    
    string s1 = "", s2 = "", s3= "";
    int s1_[105],s2_[105],s3_[105];
    for(int i = 0 ; i<len;i++)
    {
        if('a' <= s[i] && 'i' >= s[i])
        {
            s1+=s[i];
            s1_[s1.length()-1] = i;
        }
        else if('j' <= s[i] && 'r' >= s[i])
        {
            s2+=s[i];
            s2_[s2.length()-1] = i;
        }
        else{
            s3+=s[i];
            s3_[s3.length()-1] = i;
        }
    }
    k_1 %= s1.length();
    k_2 %= s2.length();
    k_3 %= s3.length();
    string ts1 = "";string ts2 = "";string ts3 = "";
    for(int i = 0 ;i<s1.length();i++)
    {
        ts1 += s1[(i + s1.length() - k_1) % s1.length()];
     } 
     
    for(int i = 0 ;i<s2.length();i++)
    {
        ts2 += s2[(i + s2.length() - k_2) % s2.length()];
     } 
    
    for(int i = 0 ;i<s3.length();i++)
    {
        ts3 += s3[(i + s3.length() - k_3) % s3.length()];
     } 
     string ans = s;
     for(int i = 0 ;i<ts1.length();i++)
     {
         ans[s1_[i]] = ts1[i];
     }
     for(int i = 0 ;i<ts2.length();i++)
     {
         ans[s2_[i]] = ts2[i];
     }
     for(int i = 0 ;i<ts3.length();i++)
     {
         ans[s3_[i]] = ts3[i];
     }
     return ans;
}
int main()
{
    while(cin >> k_1 >> k_2 >> k_3)
    {
        if(k_1 == 0 && k_2 == 0 && k_3 == 0)
        return 0;
        
        string s ;
        cin >> s;
        cout << solve(s) <<endl;
    }
}

发表于 2019-02-28 21:33:33 回复(0)
/* 分组右移,关键在于右移后的下标值计算。如果是加密左移要考虑下标可能出现的负值。 */
#include <stdio.h>
#include <string.h>
#include <vector>
#include <map>

using namespace std;

struct word {
    int k;
    int idx;
    char c;
};

int k1, k2, k3;
int getk(char c)
{
    if (c >= 'a' && c <= 'i')
        return k1;
    else if (c >= 'j' && c <= 'r')
        return k2;
    else if (c >= 's' && c <= 'z' || c == '_')
        return k3;

    printf("invalid %c\n", c);
    return -1;
}

int main()
{
    while (scanf("%d%d%d", &k1, &k2, &k3) != EOF) {
        if (k1 == 0 && k2 == 0 && k3 == 0)
            break;
        map<int, int> m;
        m[k1] = 0;
        m[k2] = 1;
        m[k3] = 2;

        char str[81];
        scanf("%s", str);

        vector<word> vec[3];
        for (int i = 0; i < strlen(str); ++i) {
            int k = getk(str[i]);
            word w;
            w.k   = k;
            w.idx = i;
            w.c   = str[i];
            vec[m[k]].push_back(w);
        }

        for (int i = 0; i < 3; ++i) {
            int size = vec[i].size();
            for (int j = 0; j < size; ++j) {
                word x = vec[i][j];
                word y = vec[i][(j+x.k)%size];
                str[y.idx] = x.c;
            }
        }

        printf("%s\n", str);
    }

    return 0;
}

编辑于 2019-01-24 16:22:47 回复(0)
放在博客里面了,http://t.cn/E52ozOF
发表于 2019-01-18 21:27:49 回复(0)
#include <iostream>
#include <string>
using namespace std;
int k[3];
string encryptedStr;
char part[3][1000];
int partIndex[3][1000];//对应在string当中的位置
int partNum[3] = { 0 };//对应在char数组中的位置

//将数据拆分为三组,当然这里还可以用循环更加简洁一点
void departStr(){
    int i;
    for (i = 0; i < encryptedStr.length(); i++){
        if (encryptedStr[i] >= 'a'&&encryptedStr[i] <= 'i'){
            part[0][partNum[0]] = encryptedStr[i];
            partIndex[0][partNum[0]] = i;
            partNum[0]++;
        }
        else if (encryptedStr[i] >= 'j'&&encryptedStr[i] <= 'r'){
            part[1][partNum[1]] = encryptedStr[i];
            partIndex[1][partNum[1]] = i;
            partNum[1]++;
        }
        else{
            part[2][partNum[2]] = encryptedStr[i];
            partIndex[2][partNum[2]] = i;
            partNum[2]++;
        }
    }
}

void decrypt(){
    int i, j;
    for (i = 0; i < 3; i++){//循环k
        for (j = 0; j < partNum[i]; j++){
            encryptedStr[partIndex[i][(j + k[i]) % partNum[i]]]=part[i][j];
        }
    }
}

int main(int argc)
{
    while (cin>>k[0]>>k[1]>>k[2])
    {
        if (k[0] == 0 && k[1] == 0 && k[2] == 0){
            break;
        }
        partNum[0] = 0;
        partNum[1] = 0;
        partNum[2] = 0;
        cin >> encryptedStr;
        departStr();
        decrypt();
        cout << encryptedStr << endl;
    }

    return 0;
}
发表于 2018-08-17 11:05:36 回复(0)
//考点:W氏密码,多数组,二维数组
//时间复杂度S(n)=O(n), n为输入的数组长度
//思路步骤:1.使用str1、str2、str3分别接收三种不同类型的数组,它们的索引号分别使用site1、site2、site3三个数组存储
//2.初始re作为结果接收的数组,以上三个数组的大小均为MAX_VAL,不放宏定义为1000
//3.从键盘接收三个不全为零的整数k1、k2、k3
//4.输入等待加密的字符串str;
//5.在a~i, j~r, s~z三种类型中对str串进行分类,记录对应字符和字符的位置
//6.完毕后i置0,接收re[site1[(i + k1) % count1]] = str1[i]; i++
//7.重复str2, str3分别对re的赋值
//8.0~count-1,输入结果数组re
#include<bits/stdc++.h>
using namespace std;
#define MAX_VAL 1000
int main(int argc, char** agrgv){//char类型
    string str;
    int k1, k2, k3;
    while(cin>>k1>>k2>>k3 && (k1 != 0 || k2 != 0 || k3 != 0)){//从键盘接受输入三个不全为零的数
        int i = 0, count = 0, count1 = 0, count2 = 0, count3 = 0;
        int site1[MAX_VAL], site2[MAX_VAL], site3[MAX_VAL];//接收索引序号
        char str1[MAX_VAL], str2[MAX_VAL], str3[MAX_VAL];//接收每个char字符
        char re[MAX_VAL];//结果字符数组
        if(cin>>str){
            count = str.length();//求字符串长度
            //一次接收读入的字符与位置到相应的存储数组
            while(i < count){
                if(str[i] >= 'a' && str[i] <= 'i'){
                    str1[count1] = str[i];
                    site1[count1] = i;
                    count1++;
                }else if(str[i] >= 'j' && str[i] <= 'r'){
                    str2[count2] = str[i];
                    site2[count2] = i;
                    count2++;
                }else if(str[i] >= 's' && str[i] <= 'z' || str[i] == '_'){
                    str3[count3] = str[i];
                    site3[count3] = i;
                    count3++;
                }
                i++;
            }
            i = 0;
            while(i < count1){
                re[site1[(i + k1) % count1]] = str1[i];
                i++;
            }
            i = 0;
            while(i < count2){
                re[site2[(i + k2) % count2]] = str2[i];
                i++;
            }
            i = 0;
            while(i < count3){
                re[site3[(i + k3) % count3]] = str3[i];
                i++;
            }
            for(i = 0;  i < count; i++){
                cout<<re[i];
            }
            cout<<endl;
        }
    }
    return 0;
}
发表于 2018-03-07 11:04:36 回复(0)
#include <stdio.h>
#include <string.h>
//#include <conio.h>
//k1 k2 k3
//[a-i][j-r][s-z,underscore]
//each group rotated left by ki positions

//把字符串里所有字符循环左移p位(p可能大于数组长度 故要%数组长度)
void rotate(char s[],int p){
    int n = strlen(s);
    p%=n;
    char temp[n+1];
    strcpy(temp,s);
    for(int i=0;i<n;i++){
        s[i]=temp[(i+n-p)%n];
    }
}
int main(){
    //freopen("C:\\Users\\Administrator\\Desktop\\in.txt","r",stdin);
    int k1,k2,k3;
    char s[100];
    while(~scanf("%d %d %d",&k1,&k2,&k3)){
        if(k1==0&&k2==0&&k3==0) break;
        scanf("%s",s);
        int t[100]={0};//t[i]表示s[i]的字符的组数
        char s1[85],s2[85],s3[85];//分别存放3个组的字符
        int n1=0,n2=0,n3=0;
        int n = strlen(s);
        for(int i=0;i<n;i++){
            if(s[i]<='i'&&s[i]>='a'){
                s1[n1++]=s[i];
                t[i]=1;
            }else if(s[i]<='r'&&s[i]>='j'){
                s2[n2++]=s[i];
                t[i]=2;
            }else{
                s3[n3++]=s[i];
                t[i]=3;
            }
        }
        s1[n1]='\0';
        s2[n2]='\0';
        s3[n3]='\0';
        //循环左移
        if(n1!=0)
            rotate(s1,k1);
        if(n2!=0)
            rotate(s2,k2);
        if(n3!=0)
            rotate(s3,k3);
        int i1=0,i2=0,i3=0;
        for(int i=0;i<n;i++){
            if(t[i]==1){
                s[i]=s1[i1++];
            }else if(t[i]==2){
                s[i]=s2[i2++];
            }else s[i]=s3[i3++];
        }
        printf("%s\n",s);
    }
    //fclose(stdin);
    //getch();
    return 0;
}

发表于 2018-02-28 18:45:43 回复(0)
#include <iostream>
#include <string>
#define MAX_VAL 81
using namespace std;
int main(int argc, char** argv) 
{    
    int k1,k2,k3;string str;
    while(cin>>k1>>k2>>k3 && (k1 != 0 || k2 != 0 || k3 != 0))
    {
        int count1 = 0,count2 = 0,count3 = 0,count = 0,i = 0;
        char str1[MAX_VAL],str2[MAX_VAL],str3[MAX_VAL],re[MAX_VAL];
        int site1[MAX_VAL],site2[MAX_VAL],site3[MAX_VAL];
        if(cin>>str)
        {
            count = str.length();
            while(i < count)
            {
                if(str[i] >= 'a' && str[i] <= 'i')
                {str1[count1] = str[i];site1[count1] = i;count1++;}
                else if(str[i] >= 'j' && str[i] <= 'r')
                {str2[count2] = str[i];site2[count2] = i;count2++;}
                else if((str[i] >= 's' && str[i] <= 'z') || str[i] == '_')
                {str3[count3] = str[i];site3[count3] = i;count3++;}
                i++;
            }
            i = 0;while(i < count1){re[site1[(i + k1) % count1]] = str1[i];i++;}
            i = 0;while(i < count2){re[site2[(i + k2) % count2]] = str2[i];i++;}
            i = 0;while(i < count3){re[site3[(i + k3) % count3]] = str3[i];i++;}
            for(i = 0;i < count;i++)cout<<re[i];
            cout<<endl;    
        }
    }
    return 0;
}
发表于 2018-02-12 20:56:49 回复(0)
啥头像
先分组
再循环右移
然后重组
def decrypt(es, k1, k2, k3):
    group1 = []; group2 = []; group3 = []
    for ch in es:
        if 'a'<=ch<='i':
            group1.append(ch)
        elif 'j'<=ch<='r':
            group2.append(ch)
        else:
            group3.append(ch)
    k1 = k1 % len(group1); k2 = k2 % len(group2); k3 = k3 % len(group3)
    group1 = group1[-k1:] + group1[:-k1]
    group2 = group2[-k2:] + group2[:-k2]
    group3 = group3[-k3:] + group3[:-k3]
    ci1 = ci2 = ci3 = 0
    rlt = ''
    for ch in es:
        if 'a'<=ch<='i':
            rlt += group1[ci1]
            ci1 += 1
        elif 'j'<=ch<='r':
            rlt += group2[ci2]
            ci2 += 1
        else:
            rlt += group3[ci3]
            ci3 += 1
    return rlt

while True:
    try:
        k1, k2, k3 = map(int, raw_input().split())
        es = raw_input()
        print decrypt(es, k1, k2, k3)
    except:
        break

发表于 2016-03-21 14:20:23 回复(0)

问题信息

难度:
20条回答 4558浏览

热门推荐

通过挑战的用户

查看代码
Ws Cipher