OpenJudge 1.13-51:古代密码 题解

原题链接

51:古代密码

描述(此描述太繁琐,你可以忽略,下文有注解)

古罗马帝国有一个拥有各种部门的强大政府组织。其中一个部门就是保密服务部门。为了保险起见,在省与省之间传递的重要文件中的大写字母是加密的。当时最流行的加密方法是替换和重新排列。

替换方法是将所有出现的字符替换成其它的字符。有些字符会替换成它自己。例如:替换规则可以是将‘A‘ 到 ‘Y‘替换成它的下一个字符,将‘Z‘替换成 ‘A‘,如果原词是 "VICTORIOUS" 则它变成 "WJDUPSJPVT"。(下文有注解)

排列方法改变原来单词中字母的顺序。例如:将顺序<2, 1, 5, 4, 3, 7, 6, 10, 9, 8>(原题在此处有误,此数据来自英文版)应用到 "VICTORIOUS" 上,则得到"IVOTCIRSUO"。

人们很快意识到单独应用替换方法或排列方法加密,都是很不保险的。但是如果结合这两种方法,在当时就可以得到非常可靠的加密方法。所以,很多重要信息先使用替换方法加密,再将加密的结果用排列的方法加密。用两种方法结合就可以将"VICTORIOUS" 加密成"JWPUDJSTVP"。

考古学家最近在一个石台上发现了一些信息。初看起来它们毫无意义,所以有人设想它们可能是用替换和排列的方法被加密了。人们试着解读了石台上的密码,现在他们想检查解读的是否正确。他们需要一个计算机程序来验证,你的任务就是写这个验证程序。

输入输入有两行。第一行是石台上的文字。文字中没有空格,并且只有大写英文字母。第二行是被解读出来的加密前的文字。第二行也是由大写英文字母构成的。
两行字符数目的长度都不超过100。输出如果第二行经过某种加密方法后可以产生第一行的信息,输出 "YES",否则输出"NO"。

样例输入

JWPUDJSTVP
VICTORIOUS

样例输入

YES

题解

好吧,其实这道题最难的就是描述,这道语文题 其实是这样的:

给你两个字符串,例如:

JWPUDJSTVP

VICTORIOUS(长度相等,无空格)(测试数据也没有坑人)

你只能进行两个操作,替换字母,重新排列

能否将第一行字符串 改为 第二行字符串

替换字母:

题目只是举了一个替换的例子,同一个数据没有唯一的替换规律

只要满足一 一对应就可以

ABC

ADF

是合法的(自己可以翻译成自己)

ABC

ABA

不合法("A"and"C"都翻译成了"A")

AAA

ABC

不合法("A"翻译成了三个不同答案)

重新排列:

排列方法也是随便的

没有一定规律

(说白了就是你可以随便换字母的"位置")

既然位置不做要求,你应该马上想到一个东西   桶

大致思路如下:

用p1,p2两个桶分别统计两个字符串中出现i(1,2,3,4......)次的字母种类的个数("桶中桶",此处需细细咀嚼,可结合代码)

只要桶(大桶)中内容相等就cout<<"YES"; else就NO啦

那么就上代码吧!

#include<bits/stdc++.h>
using namespace std;
string a,b;
int i,t1[150],t2[150],p1[150],p2[150],len;
//t1,t2下标为"A"~"Z"
//统计该字母出现次数
//p1,p2下标一定小于总长度(0次也统计了,但无需比较)
//统计t1及t2内容相等的桶的个数 

bool f(string a,string b)//写在函数里,(强迫症)倒没有什么特殊意义
{
     for(i=0;i<len;i++)
     {
          t1[a[i]]++;
         t2[b[i]]++;
     }

     for(i=‘A‘;i<=‘Z‘;i++)
     {
         p1[t1[i]]++;
         p2[t2[i]]++;
     }

     for(i=1;i<=len;i++)//这里的循环条件需注意一下
     if(p1[i]!=p2[i]) return false;

     return true;
}

int main()
{
    cin>>a>>b;
    len=a.size();
    if(f(a,b)) cout<<"YES";
    else cout<<"NO";
    return 0;
}

当然,这道题还有一种优化方案

可以把大桶省去(此方案也可能更好理解)

"这样不便于理解,运用桶是为了解决无序序列的比对,那么把无序变为有序,不就好了吗"

——引用自某教师

那sort一下就OK了

#include<bits/stdc++.h>
using namespace std;
string s1,s2;
int t1[150],t2[150];
int len,i;

int main()
{
    cin>>s1>>s2;
    len=s1.size();
    for(i=0;i<len;i++)
    {
        t1[s1[i]]++;
        t2[s2[i]]++;
    }
    sort(t1+‘A‘,t1+‘Z‘+1);//这里的参数注意一下
    sort(t2+‘A‘,t2+‘Z‘+1);//不理解问度娘sort的工作原理
    for(i=‘A‘;i<=‘Z‘;i++)
    {
        if(t1[i]!=t2[i])
        {
            cout<<"NO";
            return 0;
        }
    }
    cout<<"YES";
    return 0;
} 

结尾百科镇贴

原文地址:https://www.cnblogs.com/zhouzhihao/p/10225262.html

时间: 2024-10-11 16:37:41

OpenJudge 1.13-51:古代密码 题解的相关文章

古代密码

个人信息:就读于燕大本科软件工程专业 目前大三; 本人博客:google搜索"cqs_2012"即可; 个人爱好:酷爱数据结构和算法,希望将来从事算法工作为人民作出自己的贡献; 编程语言:C++ 和 Java ; 编程坏境:Windows 7 专业版 x64; 编程工具:vs2008; 制图工具:office 2010 powerpoint; 硬件信息:7G-3 笔记本; 真言 真想骂街了,缺少共同的人机,再用你就真傻了,白练,你被淘汰了 题目 总时间限制: 1000ms 内存限制:

洛谷 P1079 Vigen&#232;re 密码 题解

此文为博主原创题解,转载时请通知博主,并把原文链接放在正文醒目位置. 题目链接:https://www.luogu.org/problem/show?pid=1079 题目描述 16 世纪法国外交家 Blaise de Vigenère 设计了一种多表密码加密算法――Vigenère 密 码.Vigenère 密码的加密解密算法简单易用,且破译难度比较高,曾在美国南北战争中为 南军所广泛使用. 在密码学中,我们称需要加密的信息为明文,用 M 表示:称加密后的信息为密文,用 C 表示:而密钥是一种

【bzoj3439】kpm的mc密码 题解

题目大意: 有n个字符串,编号为1~n,求每一个字符串在其他字符串中以它为后缀的字符串中编号第k小的字符串的编号. 思路: 将字符串倒过来建Trie,记录每个结尾节点的编号(可能会有重复,所以开一个vector记录).再对trie树进行dfs序,记录结尾节点的子树区间.区间第k小,自然用可持久化线段树(由于权值就是id,所以不用离散化). 注意:dfs序在遇到结尾节点时才++记录序号的变量cnt,而且相同串的dfs序号是一样的(就是说一个结尾节点可能包含好多个不同编号的串),左区间取最前的一个(

druid-1.0.13 数据库配置文件密码加密

1.cmd 切换到druid目录  我的是C:\tool\apache-tomcat-7.0.67\webapps\projectA\WEB-INF\lib 2.运行命令 java -cp druid-1.0.13.jar com.alibaba.druid.filter.config.ConfigTools 密码 确定后会输出密码 3.配置数据源XML文件 <bean id="dataSource_sqlserver" class="com.alibaba.druid

P1906 凯撒密码 题解

原题链接 好吧,这是道冷门的题目,无意间被我找到 开始看到这道题,好迷茫 偏移量是什么呢? 题目说明更是让我疑惑不已 问了度娘才知道 第二条说明是英语构词中,字母出现频率的一个排行榜 ("e"在英语单词中出现频率最高) 那么题目的意思就是: 把第一句暗文中出现最多的字母翻译为"e(E)",求出偏移量t 这样一来题目就简单了 我的代码思路呢,就是将问题分解,用自定义函数解决小问题 那么这道题就需要 ①输入 ②求t ③翻译 ④储存 ⑤输出 但还需要注意的是 所以可以先写

10:古代密码

#include<iostream> #include<string> #include<algorithm> using namespace std; int a[30],b[30]; string sa,sb; #define rep(i,j,k) for(int i=j;i<=k;i++) bool cmp(int a,int b) { return a>b; } int main() { cin>>sa>>sb; rep(i,

centos 7 + mysql 5.7.13 重置数据库的root密码

centos 7 + mysql 5.7.13重置root密码步骤: # vi /etc/my.cnf  # [mysqld]下skip-grant-tables 内容前添加# # mysql -uroot -p 连续输入enter 进入 # use mysql # update mysql.user set authentication_string=PASSWORD('redhat') where User='root'; # grant all privileges on *.*  to

Mysql5.7.13忘记密码及创建用户

mysql 5.7.13重置root密码: 1.my.nin文件里在 [mysqld]下增加skip-grant-tables 2.cmd:net start mysql -mysql -use mysql; -UPDATE user SET authentication_string=PASSWORD(NEWPASSWORD) WHERE User=root; -FLUSH PRIVILEGES; -quit; 3.登陆 mysql 5.7.13重置root密码: 1.my.nin文件里在 [

ZSC - 1306: 沼跃鱼早已看穿了一切 - 题解

Time Limit: 1 Sec  Memory Limit: 128 MB 题目链接 : http://acm.two.moe:808/JudgeOnline/problem.php?id=1306 Description 沼跃鱼打开密码门后发现门后是一个像迷宫一样的房间,墙上的指示牌写着:房间内某处有一宝箱,但是宝箱被上锁了,钥匙在这个房间的某个角落.沼泽鱼对宝箱里有什么很感兴趣,但它必须先去拿到钥匙才可以打开宝箱.然而沼跃鱼早已看穿了一切,它看清了这个房间的布局,现在给出房间的布局图,问