Medium
Maximum Number of Occurrences of a Substring — C++
Full explanation · Time O(n) · Space O(n)
// Time: O(n)
// Space: O(n)
// rolling hash (Rabin-Karp Algorithm)
class Solution {
public:
int maxFreq(string s, int maxLetters, int minSize, int maxSize) {
static const uint64_t M = 1000000007;
static const uint64_t p = 113;
uint64_t power = pow(p, minSize - 1, M), rolling_hash = 0;
int left = 0;
unordered_map<int, int> lookup;
unordered_map<char, int> count;
for (int right = 0; right < s.length(); ++right) {
++count[s[right]];
if (right - left + 1 > minSize) {
--count[s[left]];
rolling_hash = (rolling_hash + M - (s[left] * power) % M) % M;
if (!count[s[left]]) {
count.erase(s[left]);
}
++left;
}
rolling_hash = ((rolling_hash * p) % M + s[right]) % M;
if (right - left + 1 == minSize && count.size() <= maxLetters) {
++lookup[rolling_hash];
}
}
return lookup.empty()
? 0
: max_element(lookup.cbegin(), lookup.cend(),
[](const auto& a, const auto& b) {
return a.second < b.second;
})->second;
}
private:
uint64_t pow(uint64_t a,uint64_t b, uint64_t m) {
a %= m;
uint64_t result = 1;
while (b) {
if (b & 1) {
result = (result * a) % m;
}
a = (a * a) % m;
b >>= 1;
}
return result;
}
};
// Time: O(m * n), m = 26
// Space: O(m * n)
class Solution2 {
public:
int maxFreq(string s, int maxLetters, int minSize, int maxSize) {
unordered_map<string, int> lookup;
for (int right = minSize - 1; right < s.length(); ++right) {
const auto& word = s.substr(right - minSize + 1, minSize);
if (lookup.count(word)) {
++lookup[word];
} else if (unique_count(word) <= maxLetters) {
lookup[word] = 1;
}
}
return lookup.empty()
? 0
: max_element(lookup.cbegin(), lookup.cend(),
[](const auto& a, const auto& b) {
return a.second < b.second;
})->second;
}
private:
int unique_count(const string& word) {
unordered_set<char> lookup;
for (const auto& c : word) {
lookup.emplace(c);
}
return lookup.size();
}
};