<p>Given the string <code>s</code>, return the size of the longest substring containing each vowel an even number of times. That is, &#39;a&#39;, &#39;e&#39;, &#39;i&#39;, &#39;o&#39;, and &#39;u&#39; must appear an even number of times.</p>

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

<pre>
<strong>Input:</strong> s = &quot;eleetminicoworoep&quot;
<strong>Output:</strong> 13
<strong>Explanation: </strong>The longest substring is &quot;leetminicowor&quot; which contains two each of the vowels: <strong>e</strong>, <strong>i</strong> and <strong>o</strong> and zero of the vowels: <strong>a</strong> and <strong>u</strong>.
</pre>

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

<pre>
<strong>Input:</strong> s = &quot;leetcodeisgreat&quot;
<strong>Output:</strong> 5
<strong>Explanation:</strong> The longest substring is &quot;leetc&quot; which contains two e&#39;s.
</pre>

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

<pre>
<strong>Input:</strong> s = &quot;bcbcbc&quot;
<strong>Output:</strong> 6
<strong>Explanation:</strong> In this case, the given string &quot;bcbcbc&quot; is the longest because all vowels: <strong>a</strong>, <strong>e</strong>, <strong>i</strong>, <strong>o</strong> and <strong>u</strong> appear zero times.
</pre>

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

<ul>
	<li><code>1 &lt;= s.length &lt;= 5 x 10^5</code></li>
	<li><code>s</code>&nbsp;contains only lowercase English letters.</li>
</ul>

class Solution:
    def findTheLongestSubstring(self, s: str) -> int:
        # 5 vowels, 2^5 = 32 combos, encode like 01011
        # prev loop, store number of combos for all subarrays ending in index i - 1
        #at max 32 values, each representing earliest occurence of whatever substring
        #when you add new value, check if such combo already exists
        # when converting current dict, add combo list

        ans = 0

        d = {}
        vowels = set(["a", "e", "i", "o", "u"])
        # map combo to earliest index
        for j in range(len(s)):
            cur_let = s[j]
            if cur_let in vowels:
                if cur_let == "a":
                    place = 0
                elif cur_let == "e":
                    place = 1
                elif cur_let == "i":
                    place = 2
                elif cur_let == "o":
                    place = 3
                else:
                    place = 4

                new_dict = {}

                for combo in d:
                    l = list(combo)
                    f_occur = d[combo]
                    l[place] = (l[place] + 1) % 2
                    new_dict[tuple(l)] = f_occur

                to_add = [0, 0, 0, 0, 0]
                to_add[place] = 1
                to_add = tuple(to_add)
                if to_add not in new_dict:
                    new_dict[to_add] = j

                d = new_dict
            else:
                if (0, 0, 0, 0, 0) not in d:
                    d[(0, 0, 0, 0, 0)] = j

            
            if (0, 0, 0, 0, 0) in d:
                ans = max(ans, j - d[(0, 0, 0, 0, 0)] + 1)

        return ans

        
768