目录
一、提问词
你是一个具有10年以培训经验的信息奥赛教练,现请你撰写NOIP2009提高组T1潜伏者题解,至少包括以下几个部分:
1、题目描述
2、解题思路
3、实现代码
4、代码说明
二、IMA个人知识库+DeepSeek回复
以下是基于给定的 《Noip2009提高组T1潜伏者.doc》 和 《NOIP2009 T1 潜伏者 解题报告》 撰写的完整题解:
1. 题目描述
问题要求
给定两条等长的加密信息和对应原信息,需建立密文字符到明文字符的唯一映射关系,并使用此映射翻译另一条加密信息。若出现以下情况之一则输出 Failed
:
- 映射冲突:同一密文字符对应不同明文字符
- 重复映射:不同密文字符映射到同一明文字符
- 映射不完整:未覆盖所有 26 个大写字母
输入输出格式
- 输入:共 3 行:
- 加密样本信息
- 加密样本对应的原文
- 待翻译的加密信息
- 输出:翻译结果或
Failed
2. 解题思路
核心逻辑
- 建立双映射规则:
- 用一个
map<char, cha
r>
存储 密文到明文 的映射。
- 用一个
bool[256]
数组标记明文字符是否已被映射。
- 冲突检测:
- 遍历样本字符串,对每一对字符
(y, x)
(密文 y 对应明文 x):
- 若
y
已存在映射但与原值不同,或x
已被其他密文字符映射 → 冲突。
- 完整性验证:
- 最终映射表中必须恰好包含 26 个唯一字符的映射关系。
算法流程
- 遍历加密样本和原样本,逐字符建立映射。
- 遍历中实时检测冲突,若冲突直接退出。
- 映射建立完成后,检查映射表大小是否为 26。
- 若无冲突且映射完整,翻译待解密信息;否则输出
Failed
。
3. 实现代码
#include <iostream>
#include <map>
#include <cstring>
using namespace std;
int main() {
string encry, origin, target;
map<char, char> cipher_map; // 密文到明文映射表
bool used[128] = {false}; // 记录明文字符是否被使用
bool valid = true; // 标记是否合法
cin >> encry >> origin >> target;
// 建立映射关系
for (int i = 0; i < encry.size(); ++i) {
char y = encry[i], x = origin[i];
if (cipher_map.count(y)) {
// 同一密文字符映射不同明文:冲突!
if (cipher_map[y] != x) valid = false;
} else {
// 不同密文字符映射同一明文:冲突!
if (used[x]) valid = false;
cipher_map[y] = x;
used[x] = true;
}
}
// 验证完整性(必须覆盖26字母)
if (valid && cipher_map.size() == 26) {
for (char c : target) {
cout << cipher_map[c];
}
} else {
cout << "Failed";
}
return 0;
}
4. 代码说明
- 数据结构:
cipher_map
:使用map<char, cha
r>
维护密文到明文的映射,自动处理键值唯一性。
used[128]
:ASCII 标记数组,防止不同密文字符映射到同一明文字符。
- 冲突处理逻辑:
- 第二个
if
语句检测如下两种非法情况:
- 同一密文字符被多次映射到不同明文字符
- 同一明文字符被多个密文字符映射
- 双重验证:
- 若
valid
未被标记为false
,且映射表中包含 26 个键值对时才视为合法。
- 时间复杂度:
- 遍历字符串的时间复杂度为 O(n),其中 n 为字符串长度;映射操作时间复杂度为 O(1),整体效率最优。
总结:本题通过合理使用 map
容器和标记数组,高效地完成 唯一映射约束 和 完整性验证,是模拟类问题的典型解法。
三、说明
1、撰写本文,IMA+DeepSeek参考了知识库中三篇文章,其中一篇为网上内容。