【模板】字符串哈希
题目描述
如题,给定 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 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个不同的字符串。
双模哈希模板
进制哈希。进制哈希的核心便是给出一个固定进制base,将一个串的每一个元素看做一个进制位上的数字,所以这个串就可以看做一个base进制的数,那么这个数就是这个串的哈希值;则我们通过比对每个串的的哈希值,即可判断两个串是否相同
#include<iostream>
#include<string>
#include<vector>
#include<queue>
#include<unordered_map>
#include<unordered_set>
#include<map>
#include<set>
#include<algorithm>
#include<cmath>
#include<random>
#include<ctime>
#define fi first
#define se second
using namespace std;
typedef long long ll;
typedef pair<int, int> pii;
const int mod1 = 1e9 + 7;
const int mod2 = 1e9 + 9;
vector<pii> pw;
pii base;
mt19937 rnd(time(0));
pii operator+(const pii& a, const pii& b) {
int c1 = a.fi + b.fi, c2 = a.se + b.se;
if (c1 >= mod1) c1 -= mod1;
if (c2 >= mod2) c2 -= mod2;
return { c1, c2 };
}
pii operator-(const pii& a, const pii& b) {
int c1 = a.fi - b.fi, c2 = a.se - b.se;
if (c1 < 0) c1 += mod1;
if (c2 < 0) c2 += mod2;
return { c1, c2 };
}
pii operator*(const pii& a, const pii& b) {
return { 1LL * a.fi * b.fi % mod1, 1LL * a.se * b.se % mod2 };
}
void init_strhash(int lim = 0) {
pw = vector<pii>(lim + 1);
base = { rnd() % mod1, rnd() % mod2 };
pw[0] = { 1, 1 };
for (int i = 1; i <= lim; i++) pw[i] = pw[i - 1] * base;
}
struct Str_hash {
vector<pii> v;
Str_hash() {}
// 下标 1 开始
void init(const string& s) {
int m = s.size();
v.resize(m + 1);
for (int j = 1; j <= m; j++) {
char ch = s[j - 1];
v[j] = v[j - 1] * base + make_pair(ch, ch);
}
}
pii get(int L, int R) {
return v[R] - (v[L - 1] * pw[R - L + 1]);
}
};
int main()
{
vector<pii> ans;
int n;
cin >> n;
init_strhash(n);
vector<string> vs(n);
for (int i = 0; i < n; i++) cin >> vs[i];
for (int i = 0; i < n; i++) {
Str_hash hs;
hs.init(vs[i]);
ans.push_back(hs.get(1, vs[i].size()));
}
sort(ans.begin(), ans.end());
int res = n;
for (int i = 0; i < ans.size() - 1; i++) {
if (ans[i].fi == ans[i + 1].fi && ans[i].se == ans[i + 1].se) --res;
}
cout << res;
return 0;
}
自然溢出哈希模板
#include<iostream>
#include<cstring>
typedef unsigned long long ULL;
int n, m;
const int N = 1e5 + 5, P = 131;
ULL h[N], p[N];
char s[N];
using namespace std;
ULL get(int l, int r) {
return h[r] - h[l - 1] * p[r - l + 1];
}
int main()
{
cin >> n >> m;
scanf("%s", s + 1);
p[0] = 1;
for(int i = 1;i <= n;i++) {
p[i] = p[i - 1] * P;
h[i] = h[i - 1] * P + s[i];
}
while(m--) {
int l1, r1, l2, r2;
cin >> l1 >> r1 >> l2 >> r2;
if(get(l1, r1) == get(l2, r2)) cout << "Yes" << endl;
else cout << "No" << endl;
}
return 0;
}