思维题:UVa1334-Ancient Cipher

Ancient Cipher

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 file contains several test cases. Each of them consists of 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 file are equal and do not exceed 100.

Output

For each test case, print one output line. 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
MAMA ROME
HAHA
HEHE
AAA
AAA
NEERCISTHEBEST
SECRETMESSAGES

Sample Output

YES
NO
YES
YES
NO


解题心得:

  1. 题意就是给你两个字符串,可以把一种字母替换成一种另字母(例如:a->z,y->b),也可以在字符串中将字符互相交换,问是否可以通过这两个规则将一个字符串变成另一个字符串,可以YES,否则NO。
  2. 这个题真的不要想的太复杂,首先字符串长度要相同,然后可以直接统计出每个字符在字符串中的个数,然后排序,只要两个数列是相同的就可以直接YES了。
  3. 因为可以字符互相交换,所有可以直接排序不用在意字符串本身的顺序,然后统计每个字符串的个数,只要字符种类数目相同并且相同字符个数相同就可以,因为可以替换不用在意这个数目的字符到底是什么。由于不用在意顺序,也不用在意字符本身到底是什么,所以就可以将两个字符串抽象成两个有序的数列,然后直接比较两个数列。
  4. 4.

#include<bits/stdc++.h>
using namespace std;
const int maxn = 110;
char s1[maxn],s2[maxn];
int cha1[maxn],cha2[maxn];//将两个字符串抽象成两个数列
set<char> se1;//记录第一个字符串中字符的种类
set<char> se2;//记录第二个字符串中字符的种类
int _find ()//统计出每个串的每个字符的个数
{
    int len1 = strlen(s1);
    int len2 = strlen(s2);
    for(int i=0;i<len1;i++)
        se1.insert(s1[i]);
    for(int i=0;i<len2;i++)
        se2.insert(s2[i]);

    set<char>::iterator iter;
    int t1 = 0,t2 = 0;
    for(iter = se1.begin();iter!=se1.end();iter++)
    {
        int num = 0;
        for(int i=0;i<len1;i++)
            if(s1[i] == *iter)
                num++;
        cha1[t1++] = num;

    }

    for(iter = se2.begin();iter!=se2.end();iter++)
    {
        int num = 0;
        for(int i=0;i<len2;i++)
            if(s2[i] == *iter)
                num++;
        cha2[t2++] = num;
    }
    sort(cha1,cha1+t1);
    sort(cha2,cha2+t2);
    return max(t1,t2);
}

int main()
{
    while(~scanf("%s%s",s1,s2))
    {
        if(strlen(s1) != strlen(s2))//当长度不相同可以直接排除
        {
            printf("NO\n");
            continue;
        }
        memset(cha1,0,sizeof(cha1));
        memset(cha2,0,sizeof(cha2));
        se1.clear();//别忘了要清空
        se2.clear();
        int len = _find();
        bool flag = false;
        for(int i=0;i<len;i++)
        {
            if(cha1[i] != cha2[i])//只要每个字符对应的数目相等就可以
            {
                flag = true;
                break;
            }
        }
        if(flag)
            printf("NO\n");
        else
            printf("YES\n");
    }
    return 0;
}
posted @ 2017-09-01 19:50  GoldenFingers  阅读(107)  评论(0编辑  收藏  举报