给定n个字符串S1,S2,...,Sn(均由三个大写字母组成),然后给出m个查询串,统计每个查询串在S1~Sn中出现的次数。
思路:我们要做三个字母组成的字符串所对应的数字映射,这样就可以不用遍历查询,而是直接查询该映射号的数组的值就可以得知出现的次数了。
那么问题就变成了,我们应该怎么样构造映射呢?
最开始想的是直接映射,0-25对应A-Z,然后三个位数上各自相加。但这样就有可能发生错误映射,如ABC = AAD 都是3。对应的如果是简单乘法的话也是有可能相同的。
那应该怎么解决呢?
应该这样构造:
int id = 0;
for(int i = 0; i < len; i++){
id = id*26 + (S[i] - 'A');
}
这样就保证了每三个字母的字符串是唯一映射的。
整体代码如下:
#include <iostream>
#include <string>
using namespace std;
int main(){
int n;
cin>>n;
int hashtable[20000]={0};
for(int i=0;i<n;i++){
string temp;
cin>>temp;
int sum = 0;
for(int i=0;i<temp.length();i++){
//sum*=temp[i]-'A';//不能简单直接加法或者乘法,这样会有碰巧不同字母刚好哈希值相同。
sum = sum*26+temp[i]-'A';//即每次是乘上26再加上该位数。
}
hashtable[sum]++;
}
int k;
cin>>k;
for(int i=0;i<k;i++){
string temp;
cin>>temp;
int sum = 0;
for(int i=0;i<temp.length();i++){
sum=sum*26+temp[i]-'A';
}
if(i!=k-1){
cout<<hashtable[sum]<<" ";
}
else{
cout<<hashtable[sum]<<endl;
}
}
return 0;
}