Hash适用情况:
e.g.给出一列正数(可以是很大很大的数),问没有重复出现的数有多少个?
【分析】你想用数组吗? 那么下标开多大呢?这是不是个十分严峻的问题?so,我们将利用神奇的Hash来进行一个数列的化简。
PS:由于Hans等级太低,只会写最low的Hash,此文将不断更新。
我们利用一个比较迷的质数10007作为modd,每次将数字对它取模。
但是这样就造成了1%10007==10008%10007【淌血】是不是感觉撞上了事情就不好处理了?NO!
我们可以将所有的模数0~10007建成一列结构体二维不定长数组link[i][j]来存放模数相同的数。(太迷了)
具体一点就是结构体里定义num,cnt;num表示的是具体的数值,cnt表示该数值出现的个数。定义link[i][j]表示模数为i的第j个数。
然后每次输入一个数值,计算出它的模数,接着将该模数的不定长数组全部过一遍:①遇到一样的num就cnt++并推出;②遇不到一样的num就在结尾push_back一个新的数。
最后so easy啦!统计所有的cnt就好了!
#include<cstdlib>
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
#include<vector>
using namespace std;
#define modd 10007
struct node {
int num;
int cnt;
};
vector<node> link[modd];
int main(){
int n, flag, ans = 0;
scanf("%d", &n);
for(int i = 1; i <= n; i++){
node x;
x.cnt = 1;
scanf("%d", &x.num);
int y = x.num % modd;
flag = 0;
for(int j = 0; j < link[y].size(); j++){
if(x.num == link[y][j].num){
link[y][j].cnt++;
flag = 1;
break;
}
}
if(!flag){
link[y].push_back(x);
}
}
for(int i = 0; i < modd; i++)
for(int j = 0; j < link[i].size(); j++)
if(link[i][j].cnt == 1) ans++;
printf("%d\n", ans);
return 0;
}
字符串版的Hash:
e.g.同样的求多组串中没有重复出现的串个数。
【分析】只要知道如何实现字符串和其对应的模数的转换就OK了,以下change函数将为大家展示转换过程。简单来说就是字符串转成26进制形式,再一次次的对10007取模以防万一就好了~(考虑到Hash的特殊性,顺序什么的都毫无意义啦,只要是一样的数,对应模数就会相同,同时不用考虑模数撞上,因为咱们是用不定长数组存的呀~)
#include<cstdlib>
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
#include<vector>
using namespace std;
#define modd 10007
struct node {
char sss[105];
int cnt;
};
vector<node> link[modd];
int change(char ss[105]){
int tot = 0;
for(int i = 0; i < strlen(ss); i++){
tot = (tot * 26 + (ss[i]-'a')) % modd;
}
return tot;
}
char s[105];
int main(){
int n, flag, ans = 0;
scanf("%d", &n);
/* char ch[3] = "zy";
printf("%d\n", change(ch));
*/ for(int i = 1; i <= n; i++){
scanf("%s", s);
node x;
strcpy(x.sss, s);
//puts(x.sss);
x.cnt = 1;
int y = change(s);
flag = 0;
for(int j = 0; j < link[y].size(); j++){
if(!strcmp(x.sss, link[y][j].sss)){
link[y][j].cnt++;
flag = 1;
break;
}
}
if(!flag){
link[y].push_back(x);
}
}
for(int i = 0; i < modd; i++)
for(int j = 0; j < link[i].size(); j++)
if(link[i][j].cnt == 1) ans++;
printf("%d\n", ans);
return 0;
}