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

from itertools import accumulate
import operator

class Solution:
    def findTheLongestSubstring(self, s: str) -> int:
        """
        Store (0,0,0,0,0) ... (1,1,1,1,1)
        depending on which vowel we see.

        Then compute running sum
        Suppose just 0,1
        [0,1,0,0,1,1,1,0,0]
        [0,1,1,1,0,1,0,0,0]

        """
        def convert(c):
            if c =='a':
                return vowel_masks[0]
            if c =='e':
                return vowel_masks[1]
            if c =='i':
                return vowel_masks[2]
            if c =='o':
                return vowel_masks[3]
            if c =='u':
                return vowel_masks[4]
            else:
                return 0            
        vowel_masks = [0b00001, 0b00010, 0b00100, 0b01000, 0b10000]
        vowel_labels = ['a', 'e', 'i', 'o', 'u']
        l = [convert(c) for c in s]
        
        runningSum = [0] + list(accumulate(l, operator.xor))
        print(runningSum)
        first_dict = dict()
        i=0
        while (len(first_dict) < 2**5 and i < len(runningSum)):
            if runningSum[i] not in first_dict:
                first_dict[runningSum[i]] = i
            i+=1

        last_dict = dict()
        i = len(runningSum)-1
        while (len(last_dict) < 2**5 and i >= 0):
            if runningSum[i] not in last_dict:
                last_dict[runningSum[i]] = i
            i-=1

        # Compute the max difference
        maxDiff = -1
        for val, i in first_dict.items():
            j = last_dict[val] 
            if j-i  > maxDiff:
                maxDiff = j-i
        if maxDiff != -1:
            return maxDiff
        else:
            return len(s)

418