【字串雜湊】SSL_1211 好文章
阿新 • • 發佈:2019-01-10
題意
求出一個字串中長度為的子串有多少個不同的。
思路
可拿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);
}