- Choose the invariant that makes a window valid or useful.
- Advance the right boundary and add the new element.
- Move the left boundary only as needed while maintaining the invariant and updating the answer.
Code notes
- 52 lines of C++ from the credited upstream file 3305.cpp.
- The implementation visibly relies on hash lookup.
- 2 loop blocks detected.
Complexity
Confirm that neither pointer moves backwards; if so, the scan is usually linear apart from the window’s data-structure operations.
Check the problem constraints before deciding whether this complexity will pass.
Use this to learn the idea, then write your own version.
1class Solution {2 public:3 int countOfSubstrings(string word, int k) {4 return substringsWithAtMost(word, k) - substringsWithAtMost(word, k - 1);5 }6 7 private:8 9 10 int substringsWithAtMost(const string& word, int k) {11 if (k == -1)12 return 0;13 14 int res = 0;15 int vowels = 0;16 int uniqueVowels = 0;17 unordered_map<char, int> vowelLastSeen;18 19 for (int l = 0, r = 0; r < word.length(); ++r) {20 if (isVowel(word[r])) {21 ++vowels;22 if (const auto it = vowelLastSeen.find(word[r]);23 it == vowelLastSeen.end() || it->second < l)24 ++uniqueVowels;25 vowelLastSeen[word[r]] = r;26 }27 while (r - l + 1 - vowels > k) {28 if (isVowel(word[l])) {29 --vowels;30 if (vowelLastSeen[word[l]] == l)31 --uniqueVowels;32 }33 ++l;34 }35 if (uniqueVowels == 5)36 37 38 39 res += min({vowelLastSeen['a'], vowelLastSeen['e'], vowelLastSeen['i'],40 vowelLastSeen['o'], vowelLastSeen['u']}) -41 l + 1;42 }43 44 return res;45 }46 47 bool isVowel(char c) {48 static constexpr string_view kVowels = "aeiou";49 return kVowels.find(c) != string_view::npos;50 }51};52