<p>Given a string <code>s</code>, return the maximum number of occurrences of <strong>any</strong> substring under the following rules:</p>

<ul>
	<li>The number of unique characters in the substring must be less than or equal to <code>maxLetters</code>.</li>
	<li>The substring size must be between <code>minSize</code> and <code>maxSize</code> inclusive.</li>
</ul>

<p>&nbsp;</p>
<p><strong class="example">Example 1:</strong></p>

<pre>
<strong>Input:</strong> s = &quot;aababcaab&quot;, maxLetters = 2, minSize = 3, maxSize = 4
<strong>Output:</strong> 2
<strong>Explanation:</strong> Substring &quot;aab&quot; has 2 occurrences in the original string.
It satisfies the conditions, 2 unique letters and size 3 (between minSize and maxSize).
</pre>

<p><strong class="example">Example 2:</strong></p>

<pre>
<strong>Input:</strong> s = &quot;aaaa&quot;, maxLetters = 1, minSize = 3, maxSize = 3
<strong>Output:</strong> 2
<strong>Explanation:</strong> Substring &quot;aaa&quot; occur 2 times in the string. It can overlap.
</pre>

<p>&nbsp;</p>
<p><strong>Constraints:</strong></p>

<ul>
	<li><code>1 &lt;= s.length &lt;= 10<sup>5</sup></code></li>
	<li><code>1 &lt;= maxLetters &lt;= 26</code></li>
	<li><code>1 &lt;= minSize &lt;= maxSize &lt;= min(26, s.length)</code></li>
	<li><code>s</code> consists of only lowercase English letters.</li>
</ul>

class Solution:
    def maxFreq(self, s: str, maxLetters: int, minSize: int, maxSize: int) -> int:

        final_hmap = defaultdict(int)
        initial_substr = list(s[:minSize])

        letter_set = Counter(s[:minSize])
        numDistinct = len(letter_set)
        if len(letter_set) <= maxLetters:
            final_hmap["".join(initial_substr)]+=1
        
        for i, j in zip(s, s[minSize:]):
            #print(f"i: {i}, j: {j}, substr: {initial_substr}, letter_set: {letter_set}")
            initial_substr.append(j)
            initial_substr.pop(0)
            
            letter_set[j]+=1
            if letter_set[j] == 1:
                numDistinct += 1
            letter_set[i]-=1
            if letter_set[i] == 0:
                numDistinct-=1

            #print(f"initial_substr: {initial_substr}, letter_set: {letter_set}")
            if numDistinct <= maxLetters:
                #print("inital: ", initial_substr)
                final_hmap["".join(initial_substr)]+=1
                #print("adding: ", "".join(initial_substr))
                #print("letter set: ", letter_set)
        final_ordering = [[j, i] for i, j in final_hmap.items()]
        final_ordering.sort(reverse=True)
        #print("final ordering: ", final_ordering)
        return final_ordering[0][0] if final_ordering else 0
        
19600