【基础训练-密码-频次比较】Acient cipher

问题链接UVA1339 UVALive3213 POJ2159 ZOJ2658 Ancient Cipher

问题简述:给你一串密码,一串破解后的密码,需要你来检验是否二者对应。(因为密码破解法则未知,也不是那种找规律的题,所以其实就是比较二者中不同字母出现的频次是否相等。)

问题分析:对两组字符串分别进行字母统计,接着对统计结果进行排序,然后对排序后的结果进行比较。如果相同,说明可以找到一种一一映射,使得两个字符串相同。

程序说明:比较两组非字符值是否相等,还可以使用函数memcmp()来实现。

  1. /* 
  2.     题意分析: 
  3.       有一明文(纯大写字母序列,长度<100), 
  4.       对其使用 凯撒加密(替换加密) 和 乱序加密 后得到密文 
  5.       根据这两种加密的特点,密文与明文必定等长,且同为纯大写字母序列。 
  6.       现给定一对密文和明文,猜测它们是否配对。 
  7.  
  8.       首先需要明确这两种加密方式的特点: 
  9.       ① 凯撒加密:令明文中所有字母均在字母表上向前/后以固定值偏移并替换 
  10.       ② 乱序加密:给定乱序表,交换明文中每个字母的位置 
  11.  
  12.       解题思路先入为主肯定是通过某种手段另对明文加密或对密文解密,对结果字符串进行比较. 
  13.       但是由于题目并未给出乱序表,因此此方案不可行  
  14.       (若单纯只有凯撒加密,是可以通过碰撞26次偏移值做逆向还原的, 
  15.       但由于还存在乱序加密,且乱序表的长度最大为100,根据排列组合来看是不可能的) 
  16.  
  17.  
  18.       为此切入点可以通过比较明文和密文在加密前后依然保有的共有特征,猜测两者是否配对: 
  19.       ① 明文和密文等长 
  20.       ② 乱序加密只改变了明文中字母的顺序,原本的字母并没有发生变化 
  21.       ③ 把明文中每个字母看作一个变量,凯撒加密只改变了变量名称,该变量出现的次数没有发生变化 
  22.       ④ 综合①②③的条件,若分别对明文和密文每个字母进行采样,分别求得每个字母的出现频次, 
  23.          然后对频次数列排序,若明文和密文是配对的,可以得到两个完全一样的频次数列 
  24.       ⑤ 比较频次数列会存在碰撞几率,亦即得到只是疑似解 
  25.         (但由于题目没有给出乱序表,基本不可能得到准确解,疑似解已经足够了) 
  26. */  
  27.   
  28. #include <algorithm>  
  29. #include <iostream>  
  30. using namespace std;  
  31.   
  32.   
  33. const static int MAX_LEN = 101;     // 密文/明文最大长度  
  34. const static int FRE_LEN = 26;      // 频率数组长度(记录每个字母的出现次数)  
  35.   
  36.   
  37. /*  
  38.  * 计算字符串中每个字母出现的频次 
  39.  * @param _in_txt 入参:纯大写字母的字符数组 
  40.  * @param _out_frequency 出参:长度为26的每个字母出现的频次数组 
  41.  */  
  42. void countFrequency(char* _in_txt, int* _out_frequency);  
  43.   
  44. /*  
  45.  * 比对两个频次数组是否完全一致(频次数组定长为26) 
  46.  * @param aFrequency 频次数组a 
  47.  * @param bFrequency 频次数组b 
  48.  * return true:完全一致; false:存在差异 
  49.  */  
  50. bool isSame(int* aFrequency, int* bFrequency);  
  51.   
  52.   
  53. int main(void) {  
  54.     char cipherTxt[MAX_LEN] = { '\0' };     // 密文  
  55.     char plaintTxt[MAX_LEN] = { '\0' };     // 明文  
  56.     int cFrequency[FRE_LEN] = { 0 };        // 密文频次数列  
  57.     int pFrequency[FRE_LEN] = { 0 };        // 明文频次数列  
  58.   
  59.     cin >> cipherTxt >> plaintTxt;  
  60.     countFrequency(cipherTxt, cFrequency);  
  61.     countFrequency(plaintTxt, pFrequency);  
  62.     cout << (isSame(cFrequency, pFrequency) ? "YES" : "NO") << endl;   
  63.   
  64.     //system("pause");  
  65.     return 0;  
  66. }  
  67.   
  68.   
  69. void countFrequency(char* _in_txt, int* _out_frequency) {  
  70.     for(int i = 0; *(_in_txt + i) != '\0'; i++) {  
  71.         *(_out_frequency + (*(_in_txt + i) - 'A')) += 1;   //这一步关键,意思就是计算每个字母出现的频次,把频次放到数组相应处。
  72.     }  
  73.     sort(_out_frequency, _out_frequency + FRE_LEN);     //最重要的一步!勿漏!因为涉及对照比较频次,应排序。(理解)
  74. }  
  75.   
  76. bool isSame(int* aFrequency, int* bFrequency) {  
  77.     bool isSame = true;  
  78.     for(int i = 0; i < FRE_LEN; i++) {  
  79.         isSame = (*(aFrequency + i) == *(bFrequency + i));  
  80.         if(isSame == false) {  
  81.             break;  
  82.         }  
  83.     }  
  84.     return isSame;  
  85. /* 法二:用memcmp来比较
  86. int isSame=1;
    isSame=memcmp(aFrequency,bFrequency,FRE_LEN); 
    if(isSame==0)
    return true;
    else
    return false;  */
  1. }  

学到的点:

①计算每个字母出现的频次这里,注意是“有位置”的,这里用下标来表示该字母位置的“独一无二”,所以在这放入它的频次。

②之前说过同一个序列里去找重复,通常是排序之后依次前后比较。而这里,是两个序列来比较频次数(对位置对应不要求),所以也先进行排序,然后再比较数组是否相同即可。这里可用循环来比较,也可用<string.h>中的memcmp方法(一般也可比较字符串,相同则返回0,前者较小则返回-1)来比较。

内容概要:本文围绕点云数据中孔洞修补展开研究,旨在提高重建后的三维模型质量和完整性,满足诸如虚拟现实、3D打印以及自动驾驶等多个应用场景的需求。文中深入介绍了算法的设计思路和技术细节,如通过法线估计来调整修复区域形态等关键步骤,并详细描述了实现过程中涉及的技术参数选取标准(迭代次数和自适应参数),并指出了其在整个项目实施过程里的重要意义和具体操作规范;另外,文中还强调了指导老师在学生掌握相关专业知识时所起到的支持作用。同时,它鼓励创新思维的发展,培养学生的团队合作能力和解决复杂实际问题的能力。并且明确提出了对于参与的学生将从该项目中学到完整的开发流程、提高他们的编程技能和个人创新能力的要求。 适合人群:计算机科学技术专业的本科生及研究生,尤其是有兴趣进行3D图像处理方面探索的学生群体. 使用场景及目标:适用于需要高质量还原现实世界物品特征或地貌地形的行业应用领域,如考古文物保存、建筑遗产保护等领域的数字化重建工作中,确保获得更为逼真的视觉效果。 其他说明:文中引用了一些最新的中外文献资料支持所述的观点和研究成果。此外,在实验部分提到了软件环境搭建的相关工具(Idea 和 MySQL) ,这些都是为了让读者能更好地理解和复现文中提到的研究成果提供了必要的信息.
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值
>