题目描述
如题,给定 N 个字符串(第 i 个字符串长度为 Mi,字符串内包含数字、大小写字母,大小写敏感),请求出 N 个字符串中共有多少个不同的字符串。
友情提醒:如果真的想好好练习哈希的话,请自觉。
输入格式
第一行包含一个整数 N,为字符串的个数。
接下来 N 行每行包含一个字符串,为所提供的字符串。
输出格式
输出包含一行,包含一个整数,为不同的字符串个数。
输入输出样例
输入 #1复制
5 abc aaaa abc abcc 12345
输出 #1复制
4
说明/提示
对于 30% 的数据:N≤10,Mi≈6,Mmax≤15。
对于 70% 的数据:N≤1000,Mi≈100,Mmax≤150。
对于 100% 的数据:N≤10000,Mi≈1000,Mmax≤1500。
样例说明:
样例中第一个字符串(abc)和第三个字符串(abc)是一样的,所以所提供字符串的集合为{aaaa,abc,abcc,12345},故共计4个不同的字符串。
本题是一个是一个典型的字符哈希题 ,而处理字符哈希的最常用办法是bkdr,也就是将一个字符串看作一个x进制数将字符串的每个字符康唑x进制数的每一位。并用适当的哈希函数将x进制数转化为可储存的十进制数。
#include<stdio.h>
#include<string.h>
long long z=1000005;
struct node
{
int a;
int b;
}hash[1000005];
char s[10001][1501];
int base[2000];
int HASH(char *s)//哈希函数
{
int len=strlen(s),sum=0;
for(int i=0;i<len;i++)
{
sum+=(base[i]*s[i])%z;//利用快速幂将x进制化可储存的十进制数;
}
return sum;
}
int cz(char *s1)//哈希表的查找函数;
{
int i=0,y=HASH(s1);
while(hash[(i+y)%z].a!=0&&strcmp(s[hash[(i+y)%z].a],s1)!=0&&i<z)//解决冲突;
i++;
return (i+y)%z;
}
long long PowerMode (long long a,long long b,long long mode)//快速幂;
{
long long sum=1;
a%=mode;
while(b)
{
if(b&1==1) //奇数
{
sum=(sum*a)%mode;
}
b>>=1; //除以二;
a=a*a%mode;
}
return sum;
}
int main()
{
int n,m=0;
scanf("%d",&n);
for(int i=0;i<1500;i++)
base[i]=PowerMode (131,i,z);
for(int i=0;i<n;i++)
{
scanf("%s",s[i]);
int l=cz(s[i]);
hash[l].a=i;
hash[l].b=1;//记入字符种类
}
for(int i=0;i<z;i++)
m+=hash[i].b;
printf("%d",m);
return 0;
}