HJ29. 字符串加解密
题目描述
加密规则:
- 字母:按字母表后移一位,同时改变大小写。如 a→B,A→b,z→A,Z→a。
- 数字:增加 1,9→0。
解密规则为加密的逆过程。
输入格式
- 第 1 行:明文,仅含字母和数字
- 第 2 行:密文,仅含字母和数字
输出格式
- 第 1 行:加密后的明文
- 第 2 行:解密后的密文
示例
示例 1
输入:
abcdefg1
0BCDEFGH
输出:
BCDEFGH2
9abcdefg
说明:
- 加密
abcdefg1:a→B、b→C、…、g→H,1→2 →BCDEFGH2 - 解密
0BCDEFGH:0→9、B→a、C→b、…、H→g →9abcdefg
解题思路
第一步:理解问题本质
加密是字母后移一位并切换大小写、数字 +1;解密是字母前移一位并切换大小写、数字 -1。两者互为逆过程。
第二步:暴力解法(逐类 if-else)
对每个字符分小写、大写、数字三类逐一处理。
问题:边界(z→A、Z→a、9→0)需要额外判断,代码重复。
第三步:优化解法(取模运算统一边界)
用取模运算处理循环边界,避免写多个特殊分支。
第四步:最优解法(加密/解密独立函数)
分别实现 encrypt 和 decrypt,处理单个字符:
- 加密:小写
(ch-'a'+1)%26+'A'(后移一位且变大写);大写(ch-'A'+1)%26+'a';数字(int(ch)+1)%10。 - 解密:小写
(ch-'a'-1)%26+'A'(前移一位且变大写);大写(ch-'A'-1)%26+'a';数字(int(ch)-1)%10。
def encrypt(ch: str) -> str:
if ch.islower():
return chr((ord(ch) - ord('a') + 1) % 26 + ord('A')) # a→B, z→A
if ch.isupper():
return chr((ord(ch) - ord('A') + 1) % 26 + ord('a')) # A→b, Z→a
if ch.isdigit():
return str((int(ch) + 1) % 10) # 9→0
return ch
完整代码实现
算法可视化 · 逐帧回放这道题的代码11 帧 · 录制输入
import sys
def encrypt(ch: str) -> str:
"""加密单个字符:字母后移一位并切换大小写,数字 +1"""
if ch.islower():
return chr((ord(ch) - ord('a') + 1) % 26 + ord('A')) # a→B, z→A
if ch.isupper():
return chr((ord(ch) - ord('A') + 1) % 26 + ord('a')) # A→b, Z→a
if ch.isdigit():
return str((int(ch) + 1) % 10) # 9→0
return ch
def decrypt(ch: str) -> str:
"""解密单个字符:字母前移一位并切换大小写,数字 -1"""
if ch.islower():
return chr((ord(ch) - ord('a') - 1) % 26 + ord('A')) # a→Z, b→A
if ch.isupper():
return chr((ord(ch) - ord('A') - 1) % 26 + ord('a')) # B→a, A→z
if ch.isdigit():
return str((int(ch) - 1) % 10) # 0→9
return ch
def solve() -> None:
"""主求解函数"""
plain = sys.stdin.readline().strip()
cipher = sys.stdin.readline().strip()
print(''.join(encrypt(c) for c in plain))
print(''.join(decrypt(c) for c in cipher))
if __name__ == "__main__":
solve()
示例推演
以示例 1 为例:
加密 abcdefg1:
| 字符 | 类型 | 加密 | 结果 |
|---|---|---|---|
| a | 小写 | (a-'a'+1)%26+'A' | B |
| b | 小写 | 同上 | C |
| c | 小写 | 同上 | D |
| d | 小写 | 同上 | E |
| e | 小写 | 同上 | F |
| f | 小写 | 同上 | G |
| g | 小写 | 同上 | H |
| 1 | 数字 | (1+1)%10 | 2 |
加密结果:BCDEFGH2。
解密 0BCDEFGH:
| 字符 | 类型 | 解密 | 结果 |
|---|---|---|---|
| 0 | 数字 | (0-1)%10 | 9 |
| B | 大写 | (B-'A'-1)%26+'a' | a |
| C | 大写 | 同上 | b |
| D | 大写 | 同上 | c |
| E | 大写 | 同上 | d |
| F | 大写 | 同上 | e |
| G | 大写 | 同上 | f |
| H | 大写 | 同上 | g |
解密结果:9abcdefg。
复杂度分析
| 解法 | 时间复杂度 | 空间复杂度 | 说明 |
|---|---|---|---|
| 逐类 if-else | O(L) | O(L) | 边界分支多,代码重复 |
| 取模运算统一 | O(L) | O(L) | 循环边界一次处理 |
L 为字符串长度
易错点总结
1. 字母切换大小写
加密时字母后移一位同时切换大小写,不能只后移不切换。
2. 循环边界
z 后移回到 a(加密)、a 前移回到 z(解密),9 加 1 回到 0,0 减 1 回到 9,都要用取模。
3. 加解密方向
加密是后移 +1、解密是前移 -1,两者方向相反,不要搞混。
4. 输出两行
先输出加密结果,再输出解密结果,顺序不能反。
扩展思考
- 这种单字符循环移位可统一用
(index + delta) % N表示,加密和解密只是 delta 符号相反。 - 可把加密/解密表预计算成字典,用查表替代逐个计算。