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

传送门

题目描述

如题,给定 N N N 个字符串(第 i i i 个字符串长度为 M i M_i Mi ,字符串内包含数字、大小写字母,大小写敏感),请求出 NN 个字符串中共有多少个不同的字符串。

友情提醒:如果真的想好好练习哈希的话,请自觉,否则请右转PJ试炼场:)

输入格式

第一行包含一个整数 N N N,为字符串的个数。
接下来 N N N 行每行包含一个字符串,为所提供的字符串。

输出格式

输出包含一行,包含一个整数,为不同的字符串个数。

输入输出样例
输入

5
abc
aaaa
abc
abcc
12345

输出

4

我们先来看这个哈希常数 p p p最少是多少:26个小写字母(‘a’ ~ ‘z’),26个大写字母(‘A’ ~ ‘Z’),10个数字(‘0’~‘9’),加起来一共有62个字符。

但是保险起见,最好设一个稍微大一点的质数,比如137。

接下来我们把每一个字符串的哈希值算出来,找有没有重复的就行了。

#include <bits/stdc++.h>
using namespace std;
#define MAXN 10005
const int p = 137;        //初始化哈希常数
char s[MAXN];
#define LL long long int
LL h[MAXN];
map<LL, LL> m;            //这里的map是用来判断哈希值是不是重复的,如果重复了
LL gethash(char s[])
{
    
    
	int len = strlen(s);
	LL sum = 0;
	for(int i = len - 1; i >= 0; i--)
		sum = sum * p + s[i] - '0';        //哈希函数,我把一个字符串看作一137进制数处理了
	return sum;
}
int main()
{
    
    
	int n;
	scanf("%d", &n);
	for(int i = 1; i <= n; i++)
	{
    
    
		scanf("%s", s);
		h[i] = gethash(s);
	}
	int ans = 0;
	for(int i = 1; i <= n; i++)
	{
    
    
		if(!m[h[i]])
		{
    
    
			m[h[i]] = 1;     //判断哈希值是否重复,其实双哈希最保险,但是我写的单哈希
			ans++;
		}
	}
	cout << ans << endl;
	return 0; 
}

猜你喜欢

转载自blog.csdn.net/CoderZeng/article/details/109065439