算法刷题记录:[NOIP2009]潜伏者

题目链接

https://ac.nowcoder.com/acm/contest/19306/1051

题目分析

用a、b进行映射。map或者模拟都可以。
注意两点即可:

  • a中的所有字母必须在b中出现,那么我们统计b中的所有字符再来判断a。
  • a、b不能矛盾,将b[i]储存在idx_a上即可。
    最后破译的时候,因为a、c同为密文,所以用idx_c映射回去就行。

思考进行映射或者映射回去的时候,要想清楚:数组idx的属性代表什么,a[i]的属性又是什么。
只有属性相同,才能来回映射。

AC代码

// 1.原信息的内容与加密后所的内容均由大写字母‘A’—‘Z’构成
// 2.每个字母都有密字,加密过程就是将原信息替换成密字
// 3.不同字母对应不同密字
// 利用加密前的信息和加密后的信息获取密钥
// 步骤:于原信息中的字母x,找到其在加密信息中的对应大写字母y,并认为在密码里y是x的密字
// 停止状态
//    1.所有信息扫描完毕, 26个字母在原信息中均出现过并获得了相应的“密字”
//    2.所有信息扫描完毕,但发现存在某个(或某些)字母在原信息中没有出现。
//           a的所有字母必须出现在b中
//    3.扫描中发现掌握的信息里有明显的自相矛盾或错误
#include <iostream>

using namespace std;

string a, b, c, ans;
char st1[26];
bool st2[26];

int main()
{
    cin >> a >> b >> c;
    if (a.size() != b.size()) { cout << "Failed"; return 0; }
    if (a.size() == 1 && b.size() == 1 && a[0] == 'A' && b[0] == 'A')
            { cout << "Failed"; return 0; }
        
    bool flag = true;
    
    // a的所有字母必须在b中出现,统计b的所有字母,判断a的字母是否出现
    for (int i = 0; i < b.size(); ++ i)
        st2[b[i] - 'A'] = true;
    for (int i = 0; i < a.size(); ++ i)
        if (!st2[a[i] - 'A']) { flag = false; break; }
    
    if (flag)
    {
        // 将b[i]记录在a[i]上
        for (int i = 0; i < b.size(); ++ i)
        {
            // if (a[i] == b[i]) { cout << "Failed"; return 0; }
            int pos_a = a[i] - 'A';
            if (st1[pos_a] != '\0' && (st1[pos_a] == b[i])) continue;
            if (st1[pos_a] != '\0') { flag = false; break; }
            st1[pos_a] = b[i];
        }
    }
    if (!flag) { cout << "Failed"; return 0; }
    else
    {
        for (int i = 0; i < c.size(); ++ i)
            ans.push_back(st1[c[i] - 'A']);
        cout << ans;
    }
}
posted @ 2023-05-25 21:22  想个昵称好难ABCD  阅读(17)  评论(0编辑  收藏  举报