现在的位置: 首页 > 综合 > 正文

POJ_2159

2018年04月13日 ⁄ 综合 ⁄ 共 3513字 ⁄ 字号 评论关闭

一.题目

Ancient Cipher
Time Limit: 1000MS
Memory Limit: 65536K

Description

Ancient Roman empire had a strong government system with various departments, including a secret service department. Important documents were sent between provinces
and the capital in encrypted form to prevent eavesdropping. The most popular ciphers in those times were so called substitution cipher and permutation cipher. 
Substitution cipher changes all occurrences of each letter to some other letter. Substitutes for all letters must be different. For some letters substitute letter may coincide with the original letter. For example, applying substitution cipher that changes
all letters from 'A' to 'Y' to the next ones in the alphabet, and changes 'Z' to 'A', to the message "VICTORIOUS" one gets the message "WJDUPSJPVT". 
Permutation cipher applies some permutation to the letters of the message. For example, applying the permutation <2, 1, 5, 4, 3, 7, 6, 10, 9, 8> to the message "VICTORIOUS" one gets the message "IVOTCIRSUO". 
It was quickly noticed that being applied separately, both substitution cipher and permutation cipher were rather weak. But when being combined, they were strong enough for those times. Thus, the most important messages were first encrypted using substitution
cipher, and then the result was encrypted using permutation cipher. Encrypting the message "VICTORIOUS" with the combination of the ciphers described above one gets the message "JWPUDJSTVP". 
Archeologists have recently found the message engraved on a stone plate. At the first glance it seemed completely meaningless, so it was suggested that the message was encrypted with some substitution and permutation ciphers. They have conjectured the possible
text of the original message that was encrypted, and now they want to check their conjecture. They need a computer program to do it, so you have to write one.

Input

Input contains two lines. The first line contains the message engraved on the plate. Before encrypting, all spaces and punctuation marks were removed, so the encrypted
message contains only capital letters of the English alphabet. The second line contains the original message that is conjectured to be encrypted in the message on the first line. It also contains only capital letters of the English alphabet. 
The lengths of both lines of the input are equal and do not exceed 100.

Output

Output "YES" if the message on the first line of the input file could be the result of encrypting the message on the second line, or "NO" in the other case.

Sample Input

JWPUDJSTVP
VICTORIOUS

Sample Output

YES

二.解题技巧

    这是一道简单的加密字符串的题,加密的过程主要有两部:第一步,将字母通过一种映射关系,转化为另外一个字母,这个部分有一个要求,就是每一个字母转化后仍然是唯一的;第二步是将原来的字符串按照一定的排列进行重新排列。
    从概率统计方面来看,对于第二步而言,并没有改变字符串的每个字母的统计直方图,而第一步改变了字符串中的统计直方图。虽然第一步加密虽然改变原来的字符串中的字母统计直方图,但是,在原来的字符串中直方图统计数值比较大的字母在进行映射后得到的字母的直方图统计数值也是同样大小的,因此,不管第一步加密进行怎样的字母映射,将获得的直方图进行排序,就会得到和原来的字符串的直方图进行排序后的直方图一样的,也就是说,原来的字符串的排序后的统计直方图和加密后的字符串的排序后的统计直方图是一样的,这就是解题的关键
   因此,可以分别计算加密后的字符串和原来的字符串的统计直方图,然后将统计直方图进行排序,最后比较两个排序后的统计直方图,如果相同,则输出YES,否则,输出NO。
    本题还有一个陷阱,就是在第一步加密的过程中,很容易被题目误导,以为第一步加密就是将原来的字母用字母表中后面的一个字母代替,但是题目中其实是没有规定使用什么具体的映射的,也没有规定加密中使用的排列是什么
    

三.实现代码

#include <iostream>
#include <string>
#include <algorithm>

using namespace std;
void CalHis(const string& Origin, char* Hist)
{
    if (Hist != NULL)
    {
        for (int Index = 0; Index < 26; Index++)
        {
            Hist[Index] = 1;
        }

        for (string::const_iterator Ite = Origin.begin(); Ite != Origin.end();
            Ite++)
        {
            Hist[(*Ite) - 65]++;
        }
    }
}


bool Compare(char* A, char* B)
{
    bool result = true;

    for (int Index = 0; Index < 26; Index++)
    {
        if (A[Index] != B[Index])
        {
            result = false;
            break;
        }
    }

    return result;

}


int main()
{

    char AArray[26];
    char BArray[26];

    string a, b;
    getline(cin, a);
    getline(cin, b);

    CalHis(a, AArray);
    CalHis(b, BArray);

    sort(AArray, AArray + 26);
    sort(BArray, BArray + 26);

    if (Compare(AArray, BArray))
    {
        cout << "YES";
    }
    else
    {
        cout << "NO";
    }

    return 0;
}



四.体会  

   写代码之前,一定要好好理解题意,不要把题目中的一个特例当做题目的要求来进行,这次就是在第一步加密的过程中,一直把映射过程认为是直接将字母使用字母表中后面一个字母进行替代,在写程序的时候思路倒是简单很多,但是提交后就一直WA。记得要好好看题啊

版权所有,欢迎转载,转载请注明出处,谢谢微笑

【上篇】
【下篇】

抱歉!评论已关闭.