第七届蓝桥杯大学生C组java决赛题目 密文搜索
来源:互联网 发布:如何编写python程序 编辑:程序博客网 时间:2024/05/01 17:11
标题:密文搜索
福尔摩斯从X星收到一份资料,全部是小写字母组成。
他的助手提供了另一份资料:许多长度为8的密码列表。
福尔摩斯发现,这些密码是被打乱后隐藏在先前那份资料中的。
请你编写一个程序,从第一份资料中搜索可能隐藏密码的位置。要考虑密码的所有排列可能性。
数据格式:
输入第一行:一个字符串s,全部由小写字母组成,长度小于1024*1024
紧接着一行是一个整数n,表示以下有n行密码,1<=n<=1000
紧接着是n行字符串,都是小写字母组成,长度都为8
要求输出:
一个整数, 表示每行密码的所有排列在s中匹配次数的总和。
例如:
用户输入:
aaaabbbbaabbcccc
2
aaaabbbb
abcabccc
则程序应该输出:
4
这是因为:第一个密码匹配了3次,第二个密码匹配了1次,一共4次。
解题思路:一看题目,“每行密码的所有排列在s中匹配次数的总和“,我就想用全排列然后在s中索引,然后发现字母很多重复的,就会有很多重复排列,
然后我就发现可以把s分成很多长度为八的子字符串,通过比较子字符串中字母使用次数是不是和密码中字母使用情况相同,如果相同,则该子字符串是密码所有排列中匹配的一种情况。代码如下:
import java.util.Scanner;public class Main155 {private static int count = 0;public static void main(String[] args) {Scanner sc = new Scanner(System.in);String s = sc.next();int n = sc.nextInt();for (int j = 0; j < n; j++) {char[] ps = sc.next().toCharArray();for (int i = 0; i < s.length(); i++) {//substring()方法参数的范围必须在[0,s.length()]中if (i + 8 <= s.length()) check(s.substring(i, i + 8), ps);}}System.out.println(count);}public static void check(String s, char[] ps) {boolean[] f = new boolean[8];for (int i = 0; i < s.length(); i++) {for (int j = 0; j < ps.length; j++) {if (!f[j] && s.charAt(i) == ps[j]) {f[j] = true;break;}}}for (int j = 0; j < f.length; j++) {if (!f[j]) {return;}}count++;}}
给出另一种官方算法,和上面的实现思想大同小异,但是弄懂上面方法作之后,下面的算法设计可能会让大家获益更多,更能体会算法思想的奇妙:
算法的设计根据这样一个特性:
设,n个素数的积为:m
则,m可以唯一地分解为这些素数因子。
只要把每个字母对应一个不同的素数,包含不同字母组合的集团就可以用它们的积表示。
只要判断积是否相同,就知道是否包含了同一组字母。
import java.util.Scanner;public class Main155 {// 随便取26个素数,对应26个字母static int[] prim = { 2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47, 53, 59, 61, 67, 71, 73, 79, 83, 89,97, 101 };// 统计匹配个数变量;static int count = 0;// 保存字符串(第一份资料)中所有长度为8的子字符串的素数积static long[] kkey;static int N = 8;public static void main(String[] args) {Scanner sc = new Scanner(System.in);String s = sc.next();create_kkey(s);int n = sc.nextInt();int count = 0;for (int j = 0; j < n; j++) {count += find(sc.next());}System.out.println(count);}public static void create_kkey(String s) {// 每个字母对应一个字母组合,从倒数第七个字母开始子字符串不满足长度为N;kkey = new long[s.length() - N + 1];kkey[0] = 1;for (int i = 0; i < N; i++) {kkey[0] *= prim[s.charAt(i) - 'a'];}for (int i = 1; i < kkey.length; i++) {kkey[i] = kkey[i - 1] / prim[s.charAt(i - 1) - 'a'] * prim[s.charAt(i + N - 1) - 'a'];}}public static int find(String ps) {long key = 1;for (int i = 0; i < ps.length(); i++) {key *= prim[ps.charAt(i) - 'a'];}int sum = 0;for (int i = 0; i < kkey.length; i++) {if (key == kkey[i])sum++;}return sum;}}
0 0
- 第七届蓝桥杯大学生C组java决赛题目 密文搜索
- 蓝桥杯-第七届蓝桥杯java B组决赛
- 蓝桥杯-第七届蓝桥杯java B组决赛 路径之谜
- [C++]第七届蓝桥杯决赛之广场舞
- 2015年第六届蓝桥杯C/C++程序设计本科B组决赛 密文搜索(编程大题)
- 【2015年第六届蓝桥杯C/C++程序设计本科B组决赛 密文搜索(编程大题) 】
- 蓝桥杯决赛----密文搜索
- 蓝桥杯 第六届决赛 密文搜索 JAVA
- 2015第七届蓝桥杯决赛C语言C组--五星填数(DFS)
- 2015第七届蓝桥杯决赛C语言A组--穿越雷区(DFS)
- 第七届蓝桥杯大赛个人赛决赛(软件类C语言B组)第一题:一步之遥
- 第七届蓝桥杯决赛 C语言B组 题解 第五题_广场舞
- 2015第六届蓝桥杯决赛_密文搜索
- 四川省第七届大学生程序设计竞赛-决赛 部分题解
- 第六届蓝翔杯决赛 密文搜索
- 2015蓝桥杯决赛 密文搜索(字符串)
- 蓝桥杯决赛之密文搜索
- 第五届蓝桥杯java程序设计 c组决赛试题 年龄巧合
- 博客搬家
- poj 3481 double Queue(Splay树 模板解读)
- 数值转换成大写金额运算
- 第一道非二叉树题
- 关于TCP、HTTP、Socket的自我理解
- 第七届蓝桥杯大学生C组java决赛题目 密文搜索
- git 推送多个远程仓库
- 续写
- 【04】SSH练习——简单分页查询的实现
- 解析argc argv在php中的应用
- [bzoj1001][bjoj2006] 吸氧羊♂灰太狼 最小割
- 1011. A+B和C
- 129. Sum Root to Leaf Numbers
- leetcode数组之Plus One