题意
求出一个字符串中长度为 m m m的子串有多少个不同的。
思路
m
a
p
map
map可拿50分。
字符串哈希,每次取出一段来判断是否重复。单哈希会被卡,这里用双哈希。
这位大佬写的可能比较清楚,点击这里。
代码
#include<map>
#include<cstdio>
#include<cstring>
using namespace std;
const int p1 = 19260817;
const int p2 = 23333333;
const int base1 = 89783;
const int base2 = 47881;
int N, M, ans;
int pow1[200001], pow2[200001], h1[200001], h2[200001];
char s[200001];
map<pair<int, int>, bool> t;
long long find1(int l, int r) {
return (h1[r] - (long long)h1[l - 1] * pow1[r - l + 1] % p1 + p1) % p1;//取出l到r的子串的哈希值
}
long long find2(int l,int r) {
return (h2[r] - (long long)h2[l - 1] * pow2[r - l + 1] % p2 + p2) % p2;//同上
}
int main() {
scanf("%d %d", &N, &M);
scanf("%s", s + 1);
pow1[0] = pow2[0] = 1;
for (int i = 1; i <= N; i++) {
pow1[i] = (long long)pow1[i - 1] * base1 % p1;
pow2[i] = (long long)pow2[i - 1] * base2 % p2;
h1[i] = ((long long)h1[i - 1] * base1 + s[i] - 96 + p1) % p1;
h2[i] = ((long long)h2[i - 1] * base2 + s[i] - 96 + p2) % p2;
}
for (int i = M; i <= N; i++) {
int f1 = find1(i - M + 1, i), f2 = find2(i - M + 1, i);
if (!t[make_pair(f1, f2)]) {
t[make_pair(f1, f2)] = 1;
ans++;
}
}
printf("%d", ans);
}