蓝桥杯历年真题题目及题解目录汇总
题目链接:https://www.dotcpp.com/oj/problem1828.html
题目描述
福尔摩斯从X星收到一份资料,全部是小写字母组成。
他的助手提供了另一份资料:许多长度为8的密码列表。
福尔摩斯发现,这些密码是被打乱后隐藏在先前那份资料中的。
请你编写一个程序,从第一份资料中搜索可能隐藏密码的位置。要考虑密码的所有排列可能性。
输入
输入第一行:一个字符串s,全部由小写字母组成,长度小于1024*1024
紧接着一行是一个整数n,表示以下有n行密码,1<=n<=1000
紧接着是n行字符串,都是小写字母组成,长度都为8
输出
一个整数, 表示每行密码的所有排列在s中匹配次数的总和。
样例输入
aaaabbbbaabbcccc
2
aaaabbbb
abcabccc
样例输出
4
字符串匹配,双指针,时间复杂度已经优化到线性了,但是呢,早年的蓝桥杯的数据规模有点诡异,我估算了下,1e9,不过实际的规模没那么夸张,果断AC了org
题目意思说白了就是只要扫过字符串中,和下面的密码出现的字母数相同就好
import java.util.Scanner;
public class 密文搜索_双指针 {
public static void main(String[] args) {
Scanner in = new Scanner(System.in);
char[] ch = in.next().toCharArray();
n = in.nextInt();
a = new int[n][30];
for(int i=0;i<n;i++) {
char[] s = in.next().toCharArray();
for(char c:s)
a[i][c-'a']++;
}
if(ch.length<8) {
System.out.println(0);
return;
}
int i=0,j=0;
for(j=0;j<8;j++)
cnt[ch[j]-'a']++;
getAns();
while(j<ch.length) {
cnt[ch[i++]-'a']--;
cnt[ch[j++]-'a']++;
getAns();
}
System.out.println(ans);
}
static int n,ans=0;
static int[][] a;//记录每个密码的各种字母出现的次数
static int[] cnt = new int[30];//记录当前的扫到的各种字母个数
static void getAns() {
for(int i=0;i<n;i++) {
boolean flag = true;
for(int j=0;j<26;j++)
if(cnt[j]!=a[i][j]) {
flag = false;
break;
}
if(flag)
ans++;
}
}
}