密文搜索
问题描述
福尔摩斯从X星收到一份资料,全部是小写字母组成。
他的助手提供了另一份资料:许多长度为8的密码列表。
福尔摩斯发现,这些密码是被打乱后隐藏在先前那份资料中的。
请你编写一个程序,从第一份资料中搜索可能隐藏密码的位置。要考虑密码的所有排列可能性。
数据格式:
输入第一行:一个字符串s,全部由小写字母组成,长度小于1024*1024
紧接着一行是一个整数n,表示以下有n行密码,1<=n<=1000
紧接着是n行字符串,都是小写字母组成,长度都为8
要求输出:
一个整数, 表示每行密码的所有排列在s中匹配次数的总和。
例如:
用户输入:
aaaabbbbaabbcccc
2
aaaabbbb
abcabccc
则程序应该输出:
4
这是因为:第一个密码匹配了3次,第二个密码匹配了1次,一共4次。
思路:
不需要进行模式匹配,统计密码中各字符的个数,判断与主串中长度为8的子串的各字符的个数是否相等即可,可将字母转化为数字进行比较更为方便
注意:
开辟大数组时,要将其写在主函数外
#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<cstring>
using namespace std;
char s[1100000];
int a[1100000];
int flag1[123];
int flag2[123];
int main()
{
memset(s,0,sizeof(s));
int i,j,k,r;
int sum=0;
cin>>s;
i=0;
while(s[i]!='\0')
{
a[i]=(int)s[i];//将字母转化为int类型的数字,a-z为97-122
i++;
}
int len=i;
int n;
cin>>n;
char b[9];
for(i=0;i<n;i++)
{
cin>>b;
for(j=0;j<8;j++)
flag1[(int)b[j]]++;//统计密码中各字符的个数
for(k=0;k<len-7;k++)
{
for(r=k;r<k+8;r++)
flag2[a[r]]++;//统计主串中长度为8的子串中各字符的个数
for(r=97;r<123;r++)
if(flag1[r]!=flag2[r])//判断,密码与子串的各字符的个数是否相等
break;
if(r==123)
sum++;
memset(flag2,0,sizeof(flag2));
}
memset(flag1,0,sizeof(flag1));
}
cout<<sum;
return 0;
}