title: 字符串哈希
date: 2023-05-17 19:32:26
categories:
https://www.luogu.com.cn/problem/P3370
如题,给定 N N N 个字符串(第 i i i 个字符串长度为 M i M_i Mi,字符串内包含数字、大小写字母,大小写敏感),请求出 N N N 个字符串中共有多少个不同的字符串。
友情提醒:如果真的想好好练习哈希的话,请自觉。
第一行包含一个整数 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个不同的字符串。
核心思想:将字符串看成P进制数,P的经验值是131或13331,取这两个值的冲突概率低
小技巧:取模的数用2^64,这样直接用unsigned long long存储,溢出的结果就是取模的结果
把每个字符串的值计算出来,放到vector容器中,然后再排序去重,剩下的大小就是不同的个数。
#include
using namespace std;
typedef unsigned long long ull;
const int P = 13331, N = 1010;
ull f(string s) {
s = " " + s;
ull res = 0;
for (int i = 1; i <= s.size() - 1; i++) {
res = res * P + s[i];
}
return res;
}
int main() {
#ifndef ONLINE_JUDGE
freopen("test.in", "r", stdin);
freopen("test.out", "w", stdout);
#endif
int n;
cin >> n;
vector<ull> a;
while (n--) {
string s;
cin >> s;
a.push_back(f(s));
}
std::sort(a.begin(), a.end());
a.erase(std::unique(a.begin(), a.end()), a.end());
cout << a.size() << endl;
return 0;
}
给定一个长度为 n n n 的字符串,再给定 m m m m m m 个询问,每个询问包含四个整数 l 1 , r 1 , l 2 , r 2 l_1, r_1, l_2, r_2 l1,r1,l2,r2,请你判断 [ l 1 , r 1 ] [l_1, r_1] [l1,r1] 和 [ l 2 , r 2 ] [l_2, r_2] [l2,r2] 这两个区间所包含的字符串子串是否完全相同。
字符串中只包含大小写英文字母和数字。
第一行包含整数 n n n 和 m m m,表示字符串长度和询问次数。
第二行包含一个长度为 n n n 的字符串,字符串中只包含大小写英文字母和数字。
接下来 m m m 行,每行包含四个整数 l 1 , r 1 , l 2 , r 2 l_1, r_1, l_2, r_2 l1,r1,l2,r2,表示一次询问所涉及的两个区间。
注意,字符串的位置从 1 1 1 开始编号。
对于每个询问输出一个结果,如果两个字符串子串完全相同则输出 Yes
,否则输出 No
。
每个结果占一行。
1 ≤ n , m ≤ 1 0 5 1 \le n, m \le 10^5 1≤n,m≤105
8 3
aabbaabb
1 3 5 7
1 3 6 8
1 2 1 2
Yes
No
Yes
把字符串看成一个P进制数,计算每一段的值.需要预处理出来.
#include
using namespace std;
typedef unsigned long long ull;
const int P = 13331;
const int N = 1e5 + 10;
ull p[N], h[N];
ull get(int l, int r) {
return h[r] - h[l - 1] * p[r - l + 1];
}
int main() {
#ifndef ONLINE_JUDGE
freopen("test.in", "r", stdin);
freopen("test.out", "w", stdout);
#endif
int n, m;
cin >> n >> m;
string s;
cin >> s;
s = " " + s;
p[0] = 1, h[0] = 0;
for (int i = 1; i <= n; i++) {
h[i] = h[i - 1] * P + s[i];
p[i] = p[i - 1] * P;
}
while (m--) {
int l1, l2, l3, l4;
cin >> l1 >> l2 >> l3 >> l4;
cout<<(get(l1,l2)==get(l3,l4)?"Yes":"No")<<endl;
}
return 0;
}