洛谷 P8630 [蓝桥杯 2015 国 B] 密文搜索

题目描述

福尔摩斯从 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
#include
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;
}

你可能感兴趣的:(题组,哈希算法)