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

题目描述

福尔摩斯从 X 星收到一份资料,全部是小写字母组成。

他的助手提供了另一份资料:许多长度为 88 的密码列表。

福尔摩斯发现,这些密码是被打乱后隐藏在先前那份资料中的。

请你编写一个程序,从第一份资料中搜索可能隐藏密码的位置。要考虑密码的所有排列可能性。

输入格式

输入第一行:一个字符串 ss,全部由小写字母组成,长度小于 1024 \times 10241024×1024。

紧接着一行是一个整数 n,n, 表示以下有 nn 行密码,1 \le n \le 10001≤n≤1000。

紧接着是 nn 行字符串,都是小写字母组成,长度都为 88。

输出格式

一个整数,表示每行密码的所有排列在 ss 中匹配次数的总和。

输入输出样例

输入 #1复制

aaaabbbbaabbcccc
2
aaaabbbb
abcabccc

输出 #1复制

4

说明/提示

第一个密码匹配了 33 次,第二个密码匹配了 11 次,一共 44 次。

时限 3 秒, 512M。蓝桥杯 2015 年第六届国赛

1.这个题目用的是hash算法。

2.题目的意思是吧密码打乱,也就是说重新排列,得到新的一串字符串,然后在母串当中寻找该子串。在母串找的时候必须是连续的8个。

3.那我们如何使用hash函数? 我们知道hash函数能够使相同的字符串得出的值相等,那么,如果,字符串里面的字符相对应是相等的,我们要是的通过hash函数使得他们相等:

P8630 [蓝桥杯 2015 国 B] 密文搜索_第1张图片

让这俩个字符串相等,我们可以利用字符对应的ASCII码来做一个hash值,这样的话,如果相对于字符串的全排列,那样子hash函数 得出的值会是一样的。

如果设计我刚开始设计的是让ASCII码值    乘以   字符在字母表的顺序,但是只AC了四个测试点,我们可以改为平方法。乘以俩个ASCII码值。

 

4.然后就是一些细节:我们处理母串时,每8个生成一个hash值,然后排序即可。最后拿密码串去查找对应的hash值。排序建议使用快排,查找建议使用二分。

C代码如下:

#include
#include
#define N 1050000
char s[N];
int hash[N];
int n,c[27],m;
int quicksort(int left,int right)
{
	if(left>=right) return 0;
	int i=left,j=right,t,temp=hash[left];
	while(i=temp) j--;
		while(iright) return -1;
	if(hash[left]==x) return left;
	if(hash[right]==x) return right;
	int mid=(left+right)/2;
	if(hash[mid]==x) return mid;
	else if(hash[mid]>x) chazhao(left,mid-1,x);
	else chazhao(mid+1,right,x);
}
int csh()
{
	int i,j;
	for(i=0;i<8;i++)
	{
		hash[0]+=(s[i]-'a'+1)*s[i]*s[i];
	}
	j=1;
	for(i=8;s[i];i++)
	{
		hash[j]=hash[j-1]-(s[i-8]*s[i-8]*(s[i-8]-'a'+1))+(s[i]-'a'+1)*s[i]*s[i];
		j++;
	}
	n=j;
}
int hsh(char t[])
{
	int i,k=0,j,sum=0;
	for(i=0;i<8;i++)
	{
		k+=(t[i]-'a'+1)*t[i]*t[i];
	}
	j=chazhao(0,n-1,k);
//	printf("j %d k%d",j,k);
	if(j==-1) return 0;
	for(i=j-1;i>=0&&hash[i]==k;i--)sum++;
	for(i=j+1;i

C++代码为:

#include
#include
#include
#include
using namespace std;
const int N=1050000;
char s[N];
int hashz[N];
int n,m;
int cmp(int a,int b)
{
	return a>b;
}
int csh()
{
	int i,j;
	for(i=0;i<8;i++)
	{
		hashz[0]+=(s[i]-'a'+1)*s[i]*s[i];
	}
	j=1;
	for(i=8;s[i];i++)
	{
		hashz[j]=hashz[j-1]-(s[i-8]*s[i-8]*(s[i-8]-'a'+1))+(s[i]-'a'+1)*s[i]*s[i];
		j++;
	}
	n=j;
}
int hsh(char t[])
{
	int i,k=0,j,sum=0;
	for(i=0;i<8;i++)
	{
		k+=(t[i]-'a'+1)*t[i]*t[i];
	}
	j=lower_bound(hashz,hashz+n-1,k)-hashz;
	for(i=j;i> s;
	csh();
	sort(hashz,hashz+n-1,cmp);
	cin >> m;
	for(i=0;i> t;
		sum+=hsh(t);
	}
	cout << sum << endl;
	return 0;
}

你可能感兴趣的:(蓝桥杯,c语言,算法)