Give a string, and M, L to find such a sub-string: The length is M * l, consisting of M strings with the length of L, each of which is different. (S, size () <10 ^ 5)
String hash example. Bkdrhash is used here. It is also the least commonly used type of conflict. Principle: maps a string to a value. Here we use base = 31 (generally using prime numbers ),
First, scan it again to process the hash value (inverted) of the string consisting of each seat to the end, and then calculate the haash value of the substring whose length is L.
After that, start with the enumeration and roll back each time. The complexity of max (L * M, L * (S. Size/m) can be used too. Here we use map to determine the weight. If the enumeration is scanned at the beginning, the posture cannot be crossed. The limit may be: M = 50000, L = 1, and the complexity (S, size * m) times out.
Key 1: When the hash value is obtained, + 1 is used; otherwise, the hash values of and 10 are the same.
I began to worry that the hash value will be reduced due to a negative value. In fact, it is not: first, unsigned long, automatic modulo (this is true in the recent compilation ),
Second, because each time we derive from the back: Hash [I] = hash [I + 1] * base + s [I]-'A' + 1;, the essence is automatic modulo, therefore, hash [I] = s [I]-'A' + 1 + hash [I + L] * nbase [L] (automatically modulo each step ), because s [I]-'A' + 1 is not negative
Hash [I], hash [I + L] * nbase [l]
(PS: thanks to the instructor puyijie)
# Include <iostream> # include <cstdio> # include <cstring> # include <algorithm> # include <map> # include <string> typedef unsigned long ull; using namespace STD; const int maxn = 100050; const ull base = 31; ull nbase [maxn], hash [maxn]; int M, L; Map <ull, int> MP; int main () {ull TMP; nbase [0] = 1; for (INT I = 1; I <maxn; I ++) {nbase [I] = nbase [I-1] * base ;} while (~ Scanf ("% d", & M, & L) {string s; CIN> S; int slen = S. size (); hash [slen] = 0; For (INT I = slen-1; I> = 0; I --) hash [I] = hash [I + 1] * base + s [I]-'A' + 1; // key 1int ans = 0; For (INT I = 0; I <L & I + M * l <= slen; I ++) {MP. clear (); For (Int J = I; j <I + M * l; j + = L) {TMP = hash [J]-Hash [J + L] * nbase [l]; MP [TMP] ++;} If (MP. size () = m) ans ++; For (Int J = I + M * l; j + L <= slen; j + = L) {TMP = hash [J-M * l]-Hash [J-(S-1) * l] * nbase [l]; MP [TMP] --; if (MP [TMP] = 0) MP. erase (TMP); TMP = hash [J]-Hash [J + L] * nbase [l]; MP [TMP] ++; If (MP. size () = m) ans ++ ;}} printf ("% d \ n", ANS);} return 0 ;}
Hdu4821 string Hash (bkdrhash)