洛谷 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; }