题目描述
福尔摩斯从 X 星收到一份资料,全部是小写字母组成。
他的助手提供了另一份资料:许多长为 8z 的密码列表。
福尔摩斯发现,这些密码是被打乱后隐藏在先前那份资料中的。
请你编写一个程序,从第一份资料中搜索可能隐藏密码的位置。要考虑密码的所有排列可能性。
输入格式
输入第一行:一个字符串 s,全部由小写字母组成,长度小于 1024×10241024×1024。
紧接着一行是一个整数 n, 表示以下有 n 行密码,1≤n≤1000。
紧接着是 n 行字符串,都是小写字母组成,长度都为 88。
输出格式
一个整数,表示每行密码的所有排列在 s 中匹配次数的总和。
输入输出样例
输入
aaaabbbbaabbcccc
2
aaaabbbb
abcabccc
输出
4
思路:用哈希把字符串s每八个字符转换成一个数字记录,由于密码可以随机排列,所以我们转换哈希的时候就可以按照a到z的顺序读取,然后就每输入一个密码,就判断一次,看是否存在相同的数
#include <iostream>
#include <algorithm>
#include <string>
#include <cstring>
#define ull unsigned long long
using namespace std;
string s,x;
int n;
int t[128];
ull a[2000000];
int res;
ull Hash()
{
int base=131;
ull ans=1;
for(int i='a';i<='z';i++) ans=ans*base+t[i];
return ans;
}
int main()
{
cin>>s>>n;
for(int i=0;i<=s.length()-8;i++)
{
memset(t,0,sizeof t);
for(int j=i;j<i+8;j++) t[s[j]]++;
a[i]=Hash();
}
for(int i=0;i<n;i++)
{
cin>>x;
memset(t,0,sizeof t);
for(int j=0;j<8;j++)
{
t[x[j]]++;
}
ull b=Hash();
for(int k=0;k<=s.length()-8;k++) if(a[k]==b) res++;
}
cout<<res;
return 0;
}