<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>

# Time complexity: O(n)
# We iterate through the string s exactly once. Apart from this, all operations are constant time. 
# Space complexity: O(1)
# vowel_to_bit stores 5 items whch is constant and mask_to_idx stores 32 bits O(5)+O(32)≈O(1).
class Solution:
    def findTheLongestSubstring(self, s: str) -> int:
        # Map each vowel to a unique bit representation in a 5-bit integer.
        # The bits represent 1 if vowel is odd else 0 if even.
        # a e i o u
        # 1 0 0 0 0 = 16 # if only a is odd
        # 0 1 0 0 0 = 8 # if only e is odd
        # 0 0 1 0 0 = 4 # if only i is odd
        # 0 0 0 1 0 = 2 # if only o is odd
        # 0 0 0 0 1 = 1 # if only u is odd
        vowel_to_bit = {'a':16, 'e': 8, 'i': 4, 'o':2, 'u': 1}

        # Initialize bitmask to 0 (meaning all vowels have an even count initially- when the string is empty).
        bitmask = 0
        
        # Dictionary to store the first occurrence of each bitmask. Initialize with bitmask 0 at index -1.
        # if the bitmask becomes 0 again, it means we have even count of vowels from the beginning
        mask_to_idx = [-1]*32

        # Variable to store the maximum length of the substring found.
        max_length = 0

        for i, char in enumerate(s):
            # If the current character is a vowel, toggle the corresponding bit in the bitmask.
            if char in vowel_to_bit:
                set_bit = vowel_to_bit[char]
                # XOR the bitmask with the set bit to flip the corresponding vowel's status (odd/even count).
                bitmask = bitmask ^ set_bit
            
            # If this bitmask hasn't been seen before, store the index where it occurred.
            # This helps track the start of a valid substring.
            if mask_to_idx[bitmask] == -1 and bitmask != 0:
                mask_to_idx[bitmask] = i
            else:
                # If this bitmask has been seen before, calculate the length of the substring from
                # the first occurrence of the bitmask to the current index.
                prev_idx = mask_to_idx[bitmask]
                max_length = max(max_length, i - prev_idx)
        
        # Return the maximum length of the substring found.
        return max_length
276