跟参数输出范例一样就行。得用他给的变量名。其它就是凯撒密码的形式,变成不需要key就行破译,根据图片里的频率(那个表格就是给出的频率)
2条回答 默认 最新
- qq_34370249 2022-02-25 16:37关注
package com.zhengtao; /* * @Description : * @CreateTime : 2022-02-25 15:36 */ public class Demo { /** * 这个 是 明文? */ public static final double[] ENGLISH = { 0.0855, 0.0160, 0.0316, 0.0387, 0.1210, 0.0218, 0.0209, 0.0496, 0.0733, 0.0022, 0.0081, 0.0421, 0.0253, 0.0717, 0.0747, 0.0207, 0.0010, 0.0633, 0.0673, 0.0894, 0.0268, 0.0106, 0.0183, 0.0019, 0.0172, 0.0011 }; /* * @Description: 这个 main 方法用来破解 凯撒密码 * 首先了解,什么是凯撒密码,凯撒加密(Caesar Code)是一种简单的消息编码方式:它根据字母表将消息中的每个字母移动常量位k。 * 举个例子如果k等于3,则在编码后的消息中,每个字母都会向前移动3位:a会被替换为d;b会被替换成e; * 依此类推。字母表末尾将回卷到字母表开头。于是,w会被替换为z, x会被替换为a。在解码消息的时候,每个字母会反方向移动同样的位数。 * 那么 如何破解 凯撒密码,已经很简单明了了, * @Date: 2022-02-25 16:00 * @param args * @Return: void */ public static void main(String[] args) { // 这里应该是从命令行读取的,我这里,不方便 从命令行读取,我直接写死了,题主 这里自己处理一下 String ciphertext = "asjfkljasklfjlkasjdklfjklaskldjfasfdd"; // 从题目中看, EngLish 应该是,最终比对的明文 // 手动实现 解密凯撒密码 String temp = ""; int count = 1; while(true){ temp = ""; for (int i = 0; i < ciphertext.length(); i++) { // 确保 输入的字母 是 字母 if ((ciphertext.charAt(i) > 'a' && ciphertext.charAt(i) < 'z') || (ciphertext.charAt(i) > 'A' && ciphertext.charAt(i) < 'Z')){ char ch = (char) (ciphertext.charAt(i) + count); // 凯撒编码 if (ch > 106 && ch < 97){ ch = (char) (ch - 26); } if (ch > 122){ int l = ch - 97; ch = (char) (ch - 26); } temp = ch + temp; } } count++; System.out.println("开始执行 -> " + temp); if (chiSquared(frequency(temp), ENGLISH) == 0){ break; } if (count == 26){ temp = ""; break; } } if (temp.equals("")){ System.out.println("输入与明文不对应"); }else { System.out.println("破解成功 -> " + temp); } } /* * @Description: 返回 String 中 每个字母出现的次数 * @Date: 2022-02-25 15:37 * @param str * @Return: int[] */ public static int[] count(String str){ int[] res = new int[26]; char[] chars = str.toCharArray(); for (char ch : chars) { // 小写字母 if(ch - 65 >= 0 && ch - 65 <=25){ res[ch - 65]++; } // 大写字母 if (ch - 97 >= 0 && ch - 97 <= 25){ res[ch - 97]++; } } return res; } public static double[] frequency(String str){ double[] res = new double[26]; // 每个字母出现的频率 int[] count = count(str); // 给定字符串的长度 int length = str.length(); for (int i = 0; i < count.length; i++) { res[i] = count[i] / length; } return res; } /** * @Description: 求出来 两个数组到底有多接近 如果两个数组,一模一样,则返回结果 为 0, 匹配度越高,则返回值 越小 * @Date: 2022-02-25 15:53 * @param freq * @param english * @Return: double */ public static double chiSquared(double[] freq, double[] english){ if (freq.length != english.length){ return -1; } double res = 0.0; double[] temp = new double[26]; // 求出 a - z的匹配度 for (int i = 0; i < freq.length; i++) { temp[i] = (freq[i] - english[i]) * (freq[i] - english[i]) / english[i]; } // 根据公式,将结果求和 for (double v : temp) { res += v; } return res; } }
本回答被题主选为最佳回答 , 对您是否有帮助呢?解决 无用评论 打赏 举报 编辑记录