1. 程式人生 > >【字串雜湊】SSL_1211 好文章

【字串雜湊】SSL_1211 好文章

題意

求出一個字串中長度為mm的子串有多少個不同的。

思路

mapmap可拿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); }