加密的病历单

GitHub跳转原题关系图返回列表

按加密逆序撤销三步变换:大小写反转、逆序、字母表循环右移 3,线性还原原文。

OJ: roj

题目 ID: 1137

难度:入门

标签:字符串模拟python

创建: 2026-09-29 20:26

更新: 2026-10-05 03:07

题目描述

给定一个长度小于 5050、只含大小写字母的密文字符串。原文经过三步加密得到它:

  1. 每个字母在字母表中循环左移 3 位;
  2. 字符串整体逆序;
  3. 大小写反转。

输出解密后的原文。

样例:输入 GSOOWFASOq,输出 Trvdizrrvj。

思路

加密顺序是“左移 3 → 逆序 → 大小写反转”,解密按相反顺序撤销。大小写反转和逆序都是自逆变换;左移 3 的逆是循环右移 3。对字符串先大小写反转,再逆序,最后每个字母右移 3 位即可。

参考代码

Python 版:

python
#!/usr/bin/env python3
# Author by Rainboy blog: https://rainboylv.com github: https://github.com/rainboylvx
# rbook: -> https://rbook.roj.ac.cn  https://rbook2.roj.ac.cn
# rainboy的学习导航网站: https://idx.roj.ac.cn
# create_at: 2026-07-06 10:00
# update_at: 2026-07-06 10:00

import sys

import string

SHIFT = 3  # 加密时字母表循环左移的位数,解密时右移回来

# 解密用的字母表右移 3 翻译表:'a'->'d'、'z'->'c',大小写各一套
_LOWER = string.ascii_lowercase
SHIFTED = _LOWER[SHIFT:] + _LOWER[:SHIFT]
TABLE = str.maketrans(string.ascii_letters, SHIFTED + SHIFTED.upper())


def solve() -> None:
    cipher = sys.stdin.read().strip()  # 密文,长度 < 50,只含大小写字母

    # 加密顺序:左移 3 → 逆序 → 大小写反转;解密按逆序撤销
    swapped = cipher.swapcase()   # 撤销第 3 步:大小写反转(自逆)
    reversed_ = swapped[::-1]     # 撤销第 2 步:逆序(自逆)
    print(reversed_.translate(TABLE))  # 撤销第 1 步:循环右移 3


if __name__ == "__main__":
    solve()

C++ 版(同一算法):

cpp
/**
 * Author by Rainboy blog: https://rainboylv.com github: https://github.com/rainboylvx
 * rbook: -> https://rbook.roj.ac.cn  https://rbook2.roj.ac.cn
 * rainboy的学习导航网站: https://idx.roj.ac.cn
 * create_at: 2026-10-05 03:07
 * update_at: 2026-10-05 03:07
 */

#include <iostream>
#include <algorithm>
#include <string>
using namespace std;

typedef long long ll;

string s; // 密文字符串,长度小于 50,只含大小写字母

// 把字符 c 在大小写字母环上循环右移 3 位
char shift_right(char c) {
    if (c >= 'a' && c <= 'z') return (c - 'a' + 3) % 26 + 'a';
    if (c >= 'A' && c <= 'Z') return (c - 'A' + 3) % 26 + 'A';
    return c;
}

int main() {
    ios::sync_with_stdio(false);
    cin.tie(0);

    cin >> s;

    // 解密按加密逆序撤销:先大小写反转,再逆序,最后循环右移 3
    for (ll i = 0; i < (ll)s.size(); i++) {
        if (s[i] >= 'a' && s[i] <= 'z') s[i] = s[i] - 'a' + 'A';
        else s[i] = s[i] - 'A' + 'a';
    }

    reverse(s.begin(), s.end()); // 逆序撤销

    for (ll i = 0; i < (ll)s.size(); i++) s[i] = shift_right(s[i]); // 右移 3

    cout << s << '\n';
    return 0;
}