【题解-洛谷】P3370 【模板】字符串哈希
P3370 【模板】字符串哈希
题目描述
如题,给定 N N N 个字符串(第 i i i 个字符串长度为 M i M_i Mi,字符串内包含数字、大小写字母,大小写敏感),请求出 N N N 个字符串中共有多少个不同的字符串。
友情提醒:如果真的想好好练习哈希的话,请自觉。
输入格式
第一行包含一个整数 N N N,为字符串的个数。
接下来 N N N 行每行包含一个字符串,为所提供的字符串。
输出格式
输出包含一行,包含一个整数,为不同的字符串个数。
输入输出样例 #1
输入 #1
5
abc
aaaa
abc
abcc
12345
输出 #1
4
说明/提示
数据范围
对于 30 % 30\% 30% 的数据: N ≤ 10 N\leq 10 N≤10, M i ≈ 6 M_i≈6 Mi≈6, M max ≤ 15 M_{\max}\leq 15 Mmax≤15。
对于 70 % 70\% 70% 的数据: N ≤ 1000 N\leq 1000 N≤1000, M i ≈ 100 M_i≈100 Mi≈100, M max ≤ 150 M_{\max}\leq 150 Mmax≤150。
对于 100 % 100\% 100% 的数据: N ≤ 10000 N\leq 10000 N≤10000, M i ≈ 1000 M_i≈1000 Mi≈1000, M max ≤ 1500 M_{\max}\leq 1500 Mmax≤1500。
样例说明
样例中第一个字符串 a b c \tt{abc} abc 和第三个字符串 a b c \tt{abc} abc 是一样的,所以所提供字符串的集合为 { a a a a , a b c , a b c c , 12345 } \{\tt{aaaa},\tt{abc},\tt{abcc},\tt{12345}\} {aaaa,abc,abcc,12345},故共计 4 4 4 个不同的字符串。
拓展阅读
以下的一些试题从不同层面体现出了字符串哈希算法的正确性分析。
- P12197 Hash Killer I
- P12198 Hash Killer II
- P12199 (目前无解)Hash Killer III
- P12200 Hash Killer Extra
- P12201 Hash Killer Phantasm
- P7350 「MCOI-04」Dream and Strings
代码
#include<iostream>
#include<algorithm>
#include<cstring>using namespace std;typedef unsigned long long ULL;const int MaxM = 1500 + 10, MaxN = 10000 + 10, P = 131;int N;
char str[MaxM];
ULL p[MaxN], h[MaxN], a[MaxN];ULL hashh(char str[]){memset(p, 0, sizeof p);memset(h, 0, sizeof h);p[0] = 1;int len = 0;for(int i = 1; str[i]; i ++){p[i] = p[i - 1] * P;h[i] = h[i - 1] * P + str[i];len ++;}int r = len;int l = 1;return h[r] - h[l - 1] * p[r - l + 1];
}int main(){scanf("%d", &N);for(int i = 0; i < N; i ++){scanf("%s", str + 1);a[i] = hashh(str);}sort(a, a + N);int sum = 1;for(int i = 1; i < N; i ++){if(a[i] != a[i - 1]){sum ++;}}printf("%d", sum);return 0;
}
结果