哈希

哈希

核心公式:hash[i]=(hash[i-1]*p+idz(s[i]))%k

注:为防冲突 p 取1e9+7,k 取1e9+9(减小冲突概率)

   还可做双哈希 hash[][], make_pair<   ,   >

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 华丽的分割线

idz(   )函数是将这个字符转换成一个数,如 ‘a’   --> 1 、‘b’ --> 2 、‘c’ --> 3 ······

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -  华丽的分割线

最基础的一道题:

  有n个单词,拿单词 s[1],s[2],s[3],...s[n]与 s[0] 比较,求有多少个完全与 s[0] 相同的单词(不含 s[0])。

代码:

#include <bits/stdc++.h> //OK---撒花!!!
using namespace std;
const int MAXN=1e6+10;
int n,ans=0,hash[MAXN],tot;
int p=1e9+7,k=1e9+9; //p和 k通常取一对很大的孪生素数 注:p和 k是<int>类型的!

char s[MAXN];

int idz(int x){ //把单个字符(英文字母)转换成一个数 如 a->1 , b->2 ······
x=x-'a'+1;
return x;
}
int main (){
scanf("%d",&n);

getchar(); //注:用 getchar()可以输入换行 !

gets(s);
int str1=strlen(s);
hash[0]=idz(s[0])%k;
for (int i=1;i<str1;i++){
hash[i]=hash[i-1]*p+idz(s[i])%k; //把 s 的每一位转换成一个数 ,都跟前一位有关系,所以避免重复
//cout<<hash[i]<<" ";
}
cout<<endl;
int tot=hash[str1-1]; //最后一位代表了前面的所有位,是由前面推来的。
//cout<<" "<<tot<<endl;
for (int j=1;j<=n;j++){
gets(s);
int len=strlen(s);
hash[0]=idz(s[0])%k;
//cout<<idz(s[0])<<":"<<hash[0]<<" ";
for (int i=1;i<len;i++){
hash[i]=hash[i-1]*p+idz(s[i])%k;
//cout<<hash[i]<<" ";
}
if(hash[len-1]==tot)ans++; //如果,它的最后一位与 tot 相等,那么它们两个字符数组都将相等。
cout<<ans<<endl;
}
cout<<ans<<endl;
return 0;
}

一直被困扰的问题、小错误:

1)字符的格式化输入仍不熟悉,一开始电脑会把换行读进去

  解决办法:用 getchar()

2)字符数组的每一位只能是一个字符,多个字符数组不能混为一体!

3)字符数组是从0开始计的,最后一位应为数组长-1

4)一开始把 k 用进了这个循环:for (int j=1;j<=n;j++) ,k 这个变量名已经用了,导致最后算 hash 时出错了。

 

总结:太粗心啦!!!!!

原文地址:https://www.cnblogs.com/lxy050129/p/9990406.html