洛谷 P3370 【模板】字符串哈希

时间:2022-01-14 22:32:26

P3370 【模板】字符串哈希

字符串哈希就是根据一个字符串s通过某种方法计算得到一个数字x,这样如果字符串s对应一个值y的话,可以把y保存在数组a[x]中,这样如果告诉你字符串,要得到或者修改对应的值,就比较方便。

因为这个数字通常有大小限制,字符串却是无限的,所以哈希通常会有冲突,也就是多个不同的串计算出相同的数字。

因此,哈希算法需要某些措施来减少冲突的可能,例如使算法更复杂,对同一个串多算几个数字等。

但也不是冲突越少越好的,因为减少冲突必然伴随着运算量的增加(还有编程复杂度的增加)。不可能为了使冲突消失就每次用哈希都写很长代码。因此,对于不同题目可以不同选择,比如单哈希,双哈希,甚至只对某几个位置哈希,还有几个有名的哈希算法等等。

大质数(可以用来换掉文中1000000007和1000000009):

33951943,10007,1313331

另外,1000000007和1000000009慎用,会被针对。(吃瓜群众:那你还用?我:其实多乘了个31或29之后也不要紧吧。。)

#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
struct Hasha
{
int a,b;
}hasha[11000];
char s[1600];
bool cmp(Hasha a,Hasha b)
{
return a.a<b.a;
}
int ans,n,num;
void hashx(char s[])
{
int i,hash1=0,hash2=0,len=strlen(s);
for(i=0;i<len;i++)
{
hash1=(hash1*31+s[i])%1000000007;//一种非常简单的哈希,可以简单的通过更改31还有1000000007来修改同一个字串对应的结果
hash2=(hash2*29+s[i])%1000000009;//对于每个字符串,计算出两个值
}
hasha[++num].a=hash1;
hasha[num].b=hash2;
}
int main()
{
int i;
scanf("%d",&n);
for(i=1;i<=n;i++)
{
scanf("%s",s);
hashx(s);
}
sort(hasha+1,hasha+n+1,cmp);
for(i=1;i<num;i++)
if(hasha[i].a==hasha[i+1].a&&hasha[i].b==hasha[i+1].b)//如果两个串计算出的两个值分别相等,就认为串本身也是相等的(但是仍然存在被卡掉的可能,也就是串本身不相等计算出来两个值分别相等,但这道题没有)
ans++;
printf("%d",n-ans);
return 0;
}