题目描述
福尔摩斯从 X 星收到一份资料,全部是小写字母组成。
他的助手提供了另一份资料:许多长度为 8 的密码列表。
福尔摩斯发现,这些密码是被打乱后隐藏在先前那份资料中的。
请你编写一个程序,从第一份资料中搜索可能隐藏密码的位置。要考虑密码的所有排列可能性。
输入格式
输入第一行:一个字符串 s,全部由小写字母组成,长度小于 1024×1024。
紧接着一行是一个整数 n, 表示以下有 n 行密码,1≤n≤1000。
紧接着是 n 行字符串,都是小写字母组成,长度都为 8。
输出格式
一个整数,表示每行密码的所有排列在 s 中匹配次数的总和。
输入输出样例
输入 #1
aaaabbbbaabbcccc 2 aaaabbbb abcabccc
输出 #1
4
说明/提示
第一个密码匹配了 3 次,第二个密码匹配了 1 次,一共 4 次。
时限 3 秒, 512M。蓝桥杯 2015 年第六届国赛
解题思路
这题可以使用字符串哈希,因为不用考虑字符顺序,可以先统计一个字符串中每个字符出现的次数,然后使用使用进制哈希将字符串转换为数字表示,具体操作看代码;
#include<stdio.h>
#include<string.h>
char a[1100000], b[9];
long long haxi[1100000], hx[27], left = 0, right = 8;
long long base = 131, mod = 9223372036854775807, sum = 0;
long long charge()//哈希函数
{
long long ans = 0;
for (int i = 1; i <= 26; i++)
ans = (ans * base + hx[i]) % mod;
return ans;
}
int main()
{
int i, j, n;
scanf("%s", a);//输入字符串
int k = strlen(a);
for (j = 0; j <= 7; j++)
hx[a[j] - 'a' + 1]++;
haxi[0] = charge();
while (right < k)//k个字符字符可以从左到右组成k-7个字符串转换为的数字
{
hx[a[right] - 'a' + 1]++;
hx[a[left] - 'a' + 1]--;
left++; right++;
haxi[left] = charge();
}
scanf("%d", &n);
while (n--)
{
scanf("%s", b);
for (i = 1; i <= 26; i++)//初始化
hx[i] = 0;
for (i = 0; i <= 7; i++)
hx[b[i] - 'a' + 1]++;
long long ss = charge();
for (i = 0; i <= k - 8; i++)//统计数量
if (ss == haxi[i])
sum++;
}
printf("%lld", sum);
return 0;
}