• OpenJudge NOI 1.13 51:古代密码


    【题目链接】

    OpenJudge NOI 1.13 51:古代密码

    【题目考点】

    1. 字符串

    2. 计数数组

    【解题思路】

    原文经过某种“替换方法”变为密文后,每种字符都转为某一种字符,不同的字符在替换后得到的字符不同。
    那么原文和密文的字符出现次数分布规律一定是一样的

    比如原文有两种字符出现5次,3种字符出现2次,4种字符出现1次。密文也一定有两种字符出现5次,3种字符出现2次,4种字符出现一次。虽然出现同样次数的字符不同,但分布规律一定是一样的。

    在经过替换后,即便再进行重新排列,字符出现次数的分布规律也不会改变。
    因此,只要原文和密文的字符出现次数的分布规律一样,那么原文一定可以通过替换与重新排列变为密文。

    例:
    密文:JWPUDJSTVP,字符分布:有两个字符(JP)出现2次,有6个字符(WUDSTV)出现1次。
    原文:VICTORIOUS,字符分布:有两个字符(IO)出现2次,有6个字符(VCTRUS)出现1次。
    原文和密文字符出现次数的分布相同,让原文和密文出现次数相同的字符互相替换(原文IO替换为JP,原文VCTRUS替换为WUDSTV),而后很容易找到一种位置对应关系,将字符串的字符按照某种排列顺序重新排列,得到密文字符串。

    将大写字母转为数字,数字i表示字母i+'A',也就是0对应A,1对应B,…,25对应Z。
    ct[i]表示i对应的字母出现的次数。
    先遍历字符串,统计出各个字母出现的个数,得到ct数组。
    设d数组,d[i]表示这个字符串中出现i次的字母的个数。(比如"AABBCC",出现2次的字母有2个,那么d[2]为3)
    遍历ct数组,得到d数组。
    针对原文和密文,分别得到d1,d2两个数组。如果这两个数组完全相同,即原文密文两个字符串字符出现次数的分布相同,原文可以变为密文。否则无法变为密文。

    【题解代码】

    解法1:

    • C风格 使用数组,字符数组
    #include<bits/stdc++.h>
    using namespace std;
    #define N 105
    char s1[N], s2[N];
    int d1[N], d2[N];//d1[i]:第1个字符串中出现i次的字母的个数 d2[i]:第2个字符串中出现i次的字母的个数
    void getArrD(char s[], int d[])
    {
        int len = strlen(s), ct[26] = {};
        for(int i = 0; i < len; ++i)
            ct[s[i]-'A']++;
        for(int i = 0; i < 26; ++i)
            d[ct[i]]++;    
    } 
    int main()
    {
        scanf("%s\n%s", s1, s2);
        getArrD(s1, d1);
        getArrD(s2, d2);
        for(int i = 1; i <= 100; ++i)//判断d1与d2是否完全相同 
        {
            if(d1[i] != d2[i])
            {
                printf("NO");
                return 0;
            }
        }
        printf("YES");
        return 0;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • C++风格 使用vector,string
    #include<bits/stdc++.h>
    using namespace std;
    #define N 105
    struct Node
    {
        int t, n;//出现t次的字母有n个
        Node(){}
        Node(int a, int b):t(a), n(b){}
        bool operator != (Node b)
        {
            return t != b.t || n != b.n;
        }
        bool operator < (const Node &b) const//按照出现次数升序排序 
        {
            return t < b.t;
        }
    };
    string s1, s2;
    vector<Node> v1, v2;//v1保存第1个字符串中出现几次的字母有几个 v2保存第2个字符串中出现几次的字母有几个 
    vector<Node> getVec(string s)
    {
        vector<Node> v;
        int ct[26] = {};
        for(int i = 0; i < s.length(); ++i)
            ct[s[i]-'A']++;
        for(int i = 0; i < 26; ++i)
        {
            if(ct[i] > 0)
            {
                int j;
                for(j = 0; j < v.size(); ++j)
                {
                    if(v[j].t == ct[i])
                    {
                        v[j].n++;
                        break;
                    }
                }
                if(j == v.size())//没找到 
                    v.push_back(Node(ct[i], 1));
            }
        }
        return v;
    }
    int main()
    {
        cin >> s1 >> s2;
        v1 = getVec(s1);
        v2 = getVec(s2);
        if(v1.size() != v2.size())
            cout << "NO";
        else
        {
            sort(v1.begin(), v1.end());//对v1与v2排序 
            sort(v2.begin(), v2.end());
            for(int i = 0; i < v1.size(); ++i)//判断v1与v2是否完全相同 
            {
                if(v1[i] != v2[i])
                {
                    cout << "NO";
                    return 0;
                }
            }
            cout << "YES";
        }
        return 0;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
  • 相关阅读:
    运维理想和现实,你是?
    2023自动化测试面试题(含答案)
    策略+枚举 优雅的消灭 if-else
    详解 ElasticSearch 基础教程
    保险行业大洗牌,250万线下从业人员消失的背后逻辑
    (附源码)spring boot校园二手销售网站 毕业设计 161417
    技术杂文:群晖上Docker版SVN服务器从搭建到访问的全程记录
    商品期货通用模型JF1
    Centos7服务器python2安装驱动dmPython实践
    php 进程通信系列 (二)消息队列
  • 原文地址:https://blog.csdn.net/lq1990717/article/details/125418256