题解:学而思编程 解密

【题目来源】

学而思编程:解密

【题目描述】

上一次,小猴的加密方式很快就被破解掉了,后来他学习了一个很经典的加密方式——“凯撒密码”,可是他觉得这个也很容易就会被别人破解,所以他决定创造一种“猴氏撒密码”。

和“凯撒密码”一样,“猴氏撒密码撒密码”也是利用字母向后偏移来实现的,但是他觉得偏移值如果固定的话也很容易被人破解,所以在加密后还会把这个字母再加上偏移值个数,例如 "\(a\)" 在偏移值为 \(3\) 时,会被加密为 "\(dddd\)"。如果保证明文中相邻字母加密后的字母不会相同,现在给出你一个加密后的结果,你能把明文找出来

【输入】

第一行一个仅由小写字母组成的的字符串 \(s\),表示加密后的结果。

【输出】

一个字符串表示加密前的明文。

【输入样例】

aaadddd

【输出样例】

ya

【核心思想】

  1. 问题分析:给定加密后的字符串,加密规则为:每个明文字母向后偏移 \(k\) 位(\(k\) 为偏移值),然后重复输出 \(k\) 次。例如 a 偏移 \(3\) 变为 d,再输出 \(3\) 次得到 ddd。已知相邻明文字母加密后结果不同,求明文。这是一个连续段统计 + 逆向偏移问题,关键在于识别连续相同字符段并还原原始字符。

  2. 算法选择

    • 连续段分割:扫描字符串,将连续相同字符识别为一个加密块
    • 逆向偏移:每个块的长度即为偏移值 \(k\),用该值逆向还原明文字母
  3. 关键步骤

    • 初始化:读取加密字符串 \(s[1..n]\)
    • 扫描连续段
      • k = 0:当前连续相同字符计数
      • 遍历 \(i\)\(1\)\(n\)
        • k++:当前字符计数加 \(1\)
        • s[i] != s[i+1](当前字符与下一个不同,或到达末尾):
          • 还原明文字母
            • 偏移值 = \(k\)(连续出现次数)
            • 明文字母 = (s[i] - 'a' - (k-1) % 26 + 26) % 26 + 'a'
            • 解释:加密时向后偏移了 \((k-1)\) 位(因为偏移 \(1\) 时字符不变,重复 \(1\) 次),解密时向前还原
          • 输出该字符
          • k = 0:重置计数器
    • 输出完整明文
  4. 时间/空间复杂度

    • 时间复杂度:\(O(n)\),线性扫描字符串
    • 空间复杂度:\(O(n)\),存储字符串
  5. 连续段分割的核心思想

    • 加密结构识别:由于相邻明文字母加密后结果不同,加密后的字符串天然形成"连续相同字符块"结构,每块对应一个明文字母
    • 块长度即偏移值:块的长度 \(k\) 就是该字母的偏移参数,也是重复输出次数
    • 偏移还原公式:加密时 ch = (原字符 + (k-1)) % 26,解密时 原字符 = (ch - (k-1) + 26) % 26,加 \(26\) 防止负数
    • 边界处理k-1 而非 \(k\) 是因为偏移值从 \(1\) 开始(偏移 \(1\) 表示字符不变,输出 \(1\) 次)
    • 适用于"长度编码 + 字符偏移"类加密解密问题,连续段识别将密文分割为独立块

【算法标签】

字符串入门

【代码详解】

#include <bits/stdc++.h>
using namespace std;
char s[1000005];

int main()
{
    cin >> s + 1;  // 从下标1开始读取字符串
    int n = strlen(s + 1);
    int k = 0;  // 记录当前连续相同字符的数量
    for (int i = 1; i <= n; i++)
    {
        k++;
        // 如果当前字符和下一个字符不同,或者到达字符串末尾
        if (s[i] != s[i + 1])
        {
            // 还原原始字符:从加密字符减去连续的次数(取模26)
            char ch = (s[i] - 'a' - (k - 1) % 26 + 26) % 26 + 'a';
            cout << ch;
            k = 0;  // 重置计数器
        }
    }
    return 0;
}

【运行结果】

aaadddd
ya
posted @ 2026-07-05 14:19  团爸讲算法  阅读(6)  评论(0)    收藏  举报