华为OD机试_2025 B卷_字符串加密(Python,100分)(附详细解题思路)

题目描述

给你一串未加密的字符串str,通过对字符串的每一个字母进行改变来实现加密,加密方式是在每一个字母str[i]偏移特定数组元素a[i]的量,数组a前三位已经赋值:a[0]=1,a[1]=2,a[2]=4。

当i>=3时,数组元素a[i]=a[i-1]+a[i-2]+a[i-3]。

例如:原文 abcde 加密后 bdgkr,其中偏移量分别是1,2,4,7,13。

输入描述
第一行为一个整数n(1<=n<=1000),表示有n组测试数据,每组数据包含一行,原文str(只含有小写字母,0<长度<=50)。

输出描述
每组测试数据输出一行,表示字符串的密文。

用例

输入

1
xy

输出ya
说明第一个字符x偏移量是1,即为y,第二个字符y偏移量是2,即为a。

字符串加密算法解析:如何通过动态偏移数组实现字符转换加密

1. 核心解题思路

1.1 问题拆解

要实现加密,需解决以下两个核心问题:

  1. 生成偏移数组 a
    • 根据递推公式计算每个位置的偏移量。
    • 关键点:处理大数问题(偏移量可能非常大)。
  2. 字符偏移转换
    • 将每个字符按对应的偏移量转换为新字符。
    • 关键点:字母循环处理(如 z 偏移 1 后应为 a)。

1.2 关键步骤

步骤1:生成偏移数组 a
  • 初始值
    • a[0] = 1
    • a[1] = 2
    • a[2] = 4
  • 递推公式
    • a[i] = a[i-1] + a[i-2] + a[i-3]
  • 优化:模26运算
    • 由于字母表长度为26,偏移量超过26时实际等效于 a[i] % 26
    • 例如,偏移量27等价于1(27 % 26 = 1),避免数值过大。
步骤2:字符偏移转换
  • 字符位置计算
    • 将字符转换为字母表的索引(a=0, b=1, ..., z=25)。
  • 偏移操作
    • 新位置 = (原位置 + 偏移量) % 26
  • 字符还原
    • 将计算后的索引转换回字符。

2. 代码实现与详细注释

Python代码

n = int(input())  # 读取测试用例数量
for _ in range(n):
    s = input().strip()  # 读取原文
    m = len(s)
    a = []  # 初始化偏移数组
    
    # 填充前三个元素(注意字符串长度可能小于3)
    if m >= 1:
        a.append(1)
    if m >= 2:
        a.append(2)
    if m >= 3:
        a.append(4)
    
    # 生成后续元素(i从3到m-1)
    for i in range(3, m):
        # 计算当前偏移量并取模26
        next_val = (a[i-1] + a[i-2] + a[i-3]) % 26
        a.append(next_val)
    
    # 加密每个字符
    encrypted = []
    for i in range(m):
        # 将字符转换为0-25的索引
        original_pos = ord(s[i]) - ord('a')
        # 计算新位置并取模26
        new_pos = (original_pos + a[i]) % 26
        # 转换回字符
        encrypted_char = chr(new_pos + ord('a'))
        encrypted.append(encrypted_char)
    
    # 输出结果
    print(''.join(encrypted))

代码解析

2.1 生成偏移数组 a
  • 边界处理:当字符串长度小于3时,仅填充有效的前几个元素。
    if m >= 1: a.append(1)
    if m >= 2: a.append(2)
    if m >= 3: a.append(4)
    
  • 递推优化:每次计算新偏移量时对26取模。
    next_val = (a[i-1] + a[i-2] + a[i-3]) % 26
    
2.2 字符偏移转换
  • ASCII转换
    • ord('a') 返回字母 a 的ASCII码(97)。
    • chr(97) 返回ASCII码对应的字符(a)。
  • 循环处理
    new_pos = (original_pos + a[i]) % 26
    

3. 复杂度分析

  • 时间复杂度:O(n * m)
    • 外层循环处理 n 组测试数据。
    • 内层生成偏移数组和字符转换的时间复杂度为 O(m)。
  • 空间复杂度:O(m)
    • 存储偏移数组 a 和加密结果。

4. 优化与扩展

4.1 预计算偏移数组

  • 若多组测试数据中字符串长度较大,可预先生成长度固定的偏移数组缓存,避免重复计算。

4.2 大数处理的数学依据

  • 由于 a[i] 的偏移量对26取模,递推公式可简化为:
    a[i] = (a[i-1] + a[i-2] + a[i-3]) % 26
    
  • 该优化使得即使 i 很大时,计算也不会溢出。

4.3 扩展功能

  • 解密算法:逆向操作,将偏移量取反(即 new_pos = (original_pos - a[i]) % 26)。

5. 测试与验证

测试用例1

  • 输入
    1
    xy
    
  • 输出ya
  • 解释
    • x → 索引23 → 23 + 1 = 24 → y
    • y → 索引24 → 24 + 2 = 26 → 26 % 26 = 0 → a

测试用例2

  • 输入
    2
    abcde
    zzz
    
  • 输出
    bdgkr
    cba
    
  • 解释
    • a 偏移1 → b
    • b 偏移2 → d
    • c 偏移4 → g
    • d 偏移7 → k3 + 7 = 10 → 'k'
    • e 偏移13 → r4 + 13 = 17 → 'r'
    • zzz 偏移量为 1,2,4 → 依次变为 c, b, a

6. 总结

通过动态规划生成偏移数组,并结合模运算处理字符循环,本方法能够高效解决字符串加密问题。代码实现中,通过逐层分解问题、边界条件处理和数学优化,确保了算法的正确性和性能。此思路还可扩展至其他需要周期性偏移的场景(如凯撒密码变种)。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值