另一道hash题
#include <cstdio> #include <cstring> #include <algorithm> #include <string> #define LL long long using namespace std; const LL m1 = 999973, m2 = 1000000000 + 9; char s[5000005]; LL k, tot, ans; LL h[m1 + 5], h1[5000005], h2[5000005]; struct hash_table { LL cnt, next; string s; }a[5000005]; void add(LL k1, string s) { a[tot].s = s; a[tot].cnt = 1; a[tot].next = h[k1]; h[k1] = tot++; } void hash(LL k1, string s) { for (LL i = h[k1]; ~i; i = a[i].next) { if (a[i].s == s) { a[i].cnt++; ans = max(ans, a[i].cnt); return; } } add(k1, s); } LL ksm(LL a, LL b, LL mo) { LL base = a, ans = 1; while (b) { if (b & 1) ans = (ans * base) % mo; base = (base * base) % mo; b >>= 1; } return ans; } int main() { // freopen("loj12A.in","r",stdin); scanf("%s", s + 1); scanf("%lld", &k); tot = 0; memset(h, -1, sizeof h); LL len = strlen(s + 1); h1[0] = h2[0] = 0; LL t1 = ksm(131, k, m1); for (int i = 1; i <= len; i++) { h1[i] = (h1[i - 1] * 131 + s[i]) % m1; } string ns = string(s + 1); for (int i = 1; i <= len - k + 1; i++) { LL k1 = (((h1[i + k - 1] - h1[i - 1] * t1) % m1) + m1) % m1; hash(k1, ns.substr(i - 1, k).c_str()); } printf("%lld ", ans); return 0; }
这题主要的坑点在于我们需要hash的字符串的重复可能性极大,因此无论是多么优秀的映射算法都会出现大量冲突,此时我们需要手动使用原始的方式——传字符串来进行判重。