题目描述
如题,给定 NN 个字符串(第 ii 个字符串长度为 M_iMi,字符串内包含数字、大小写字母,大小写敏感),请求出 NN 个字符串中共有多少个不同的字符串。
友情提醒:如果真的想好好练习哈希的话,请自觉。
输入格式
第一行包含一个整数 NN,为字符串的个数。
接下来 NN 行每行包含一个字符串,为所提供的字符串。
输出格式
输出包含一行,包含一个整数,为不同的字符串个数。
输入输出样例
输入 #1复制
5 abc aaaa abc abcc 12345输出 #1复制
4说明/提示
对于 30\%30% 的数据:N\leq 10N≤10,M_i≈6Mi≈6,Mmax\leq 15Mmax≤15。
对于 70\%70% 的数据:N\leq 1000N≤1000,M_i≈100Mi≈100,Mmax\leq 150Mmax≤150。
对于 100\%100% 的数据:N\leq 10000N≤10000,M_i≈1000Mi≈1000,Mmax\leq 1500Mmax≤1500。
样例说明:
样例中第一个字符串(abc)和第三个字符串(abc)是一样的,所以所提供字符串的集合为{aaaa,abc,abcc,12345},故共计4个不同的字符串。
Tip: 感兴趣的话,你们可以先看一看以下三题:
BZOJ3097:http://www.lydsy.com/JudgeOnline/problem.php?id=3097
BZOJ3098:http://www.lydsy.com/JudgeOnline/problem.php?id=3098
BZOJ3099:http://www.lydsy.com/JudgeOnline/problem.php?id=3099
如果你仔细研究过了(或者至少仔细看过AC人数的话),我想你一定会明白字符串哈希的正确姿势的^_^
1.这题使用到了hash算法。
2.刚开始我是开了一个很大的数组,把hash值作为下标存储起来,如果已经有了,我们就不统计它,但是出错了。我换了很多的hash函数,为了保证不重复,我们每次都需要求余一个很大的质数。
3.后面我看了一些题解,发现他们写的hash函数虽然大同小异,但是最后的处理方式的将返回的hash值存储在数组里,这样hash值就能取到很大,也会避免碰撞。存放完之后就是排序,排序之后判断前后重复即可算出最终答案。
C代码如下:
#include<stdio.h>
#define N 10020
unsigned int a[N];
unsigned int SDBMHash(char *str)
{
unsigned int hash = 0;
while (*str)
{
// equivalent to: hash = 65599*hash + (*str++);
hash = (*str++) + (hash << 6) + (hash << 16) - hash;
}
return (hash >> 16) ^ (hash << 16);
}
int quicksort(int left, int right)
{
int i = left, j = right;
if (left >= right) return 0;
unsigned int t, temp = a[left];
while (i < j)
{
while (i < j && a[j] >= temp) j--;
while (i < j && a[i] <= temp) i++;
if (i < j)
{
t = a[i];
a[i] = a[j];
a[j] = t;
}
}
a[left] = a[i];
a[i] = temp;
quicksort(left, i - 1);
quicksort(i + 1, right);
}
int main()
{
int n, i;
unsigned int k = 0, sum = 0;
char s[10010];
scanf("%d", &n);
for (i = 0; i < n; i++)
{
scanf("%s", s);
a[i] = SDBMHash(s);
}
quicksort(0, n - 1);
sum = n;
for (i = 1; i < n; i++)
{
if (a[i] == a[i - 1]) sum--;
}
printf("%d", sum);
return 0;
}
C++代码如下:
#include<iostream>
#include<bits/stdc++.h>
#include<algorithm>
using namespace std;
const int N=10020;
unsigned int a[N];
unsigned int SDBMHash(char *str)
{
unsigned int hash = 0;
while (*str)
{
hash = (*str++) + (hash << 6) + (hash << 16) - hash;
}
return (hash >> 16) ^ (hash << 16);
}
bool cmp(unsigned int x,unsigned int y)
{
return x>y;
}
int main()
{
int n, i;
unsigned int k = 0, sum = 0;
char s[10010];
cin >> n;
for (i = 0; i < n; i++)
{
cin >> s;
a[i] = SDBMHash(s);
}
sort(0, n - 1,cmp);
sum = n;
for (i = 1; i < n; i++)
{
if (a[i] == a[i - 1]) sum--;
}
cout << sum << endl;
return 0;
}