字符串哈希
题目描述
如题,给定 N N N 个字符串(第 i i i 个字符串长度为 M i M_i Mi,字符串内包含数字、大小写字母,大小写敏感),请求出 N N N 个字符串中共有多少个不同的字符串。
友情提醒:如果真的想好好练习哈希的话,请自觉,否则请右转PJ试炼场:)
输入格式
第一行包含一个整数 N N N,为字符串的个数。
接下来 N N N 行每行包含一个字符串,为所提供的字符串。
输出格式
输出包含一行,包含一个整数,为不同的字符串个数。
样例
样例输入
5
abc
aaaa
abc
abcc
12345
样例输出
4
提示
对于 30 % 30\% 30% 的数据: N ≤ 10 N\leq 10 N≤10, M i ≈ 6 M_i≈6 Mi≈6, M m a x ≤ 15 Mmax\leq 15 Mmax≤15。
对于 70 % 70\% 70% 的数据: N ≤ 1000 N\leq 1000 N≤1000, M i ≈ 100 M_i≈100 Mi≈100, M m a x ≤ 150 Mmax\leq 150 Mmax≤150。
对于 100 % 100\% 100% 的数据: N ≤ 10000 N\leq 10000 N≤10000, M i ≈ 1000 M_i≈1000 Mi≈1000, M m a x ≤ 1500 Mmax\leq 1500 Mmax≤1500。
样例说明:
样例中第一个字符串(abc)和第三个字符串(abc)是一样的,所以所提供字符串的集合为{aaaa,abc,abcc,12345},故共计4个不同的字符串。
考查点:哈希,进制转换
思路
将字符串转换为一组数,转换为比较数的大小。本题字符串包含大小写字符和数字,所以设置进制为62(26+26+10)。
与《算法笔记》上不同的是,在判断数是否相同时,比如字符串转换后的一组数为x,并没有开辟记录数组num_show_times[],num_show_times[x]++,原因是转换62进制后的数太大了,似乎不能开那么大的数组。所以直接用一个数组存放n个转换后的数,将它们排序,再比较是否相同就可以了
代码
#include<bits/stdc++.h>
using namespace std;
typedef unsigned long long ull;
ull hashnum(char words[])
{
int length=strlen(words);
ull num=0;
for(int i=0;i<length;i++)
{
if(words[i]>='A' && words[i]<='Z')
{
num=num*62+words[i]-'A'+10;
}
if(words[i]>='a' && words[i]<='z')
{
num=num*62+words[i]-'a'+36;
}
if(words[i]>='0' && words[i]<='9')
{
num=num*62+words[i]-'0';
}
}
return num;
}
int main()
{
int n;
cin>>n;
char words[2000];
ull num[n];
int temp=0;
for(int i=0;i<n;i++)
{
cin>>words;
num[i]=hashnum(words);
//cout<<"hashnum: "<<num[i]<<endl;
}
sort(num,num+n);
for(int i=0;i<n;i++)
{
if(num[i]!=num[i+1])
temp++;
}
cout<<temp;
}