"""
1371. 每个元音包含偶数次的最长子字符串
给你一个字符串 s ,请你返回满足以下条件的最长子字符串的长度:
每个元音字母,即 'a','e','i','o','u' ,在子字符串中都恰好出现了偶数次。
示例 1:
输入:s = "eleetminicoworoep"
输出:13
解释:最长子字符串是 "leetminicowor" ,它包含 e,i,o 各 2 个,以及 0 个 a,u 。
示例 2:
输入:s = "leetcodeisgreat"
输出:5
解释:最长子字符串是 "leetc" ,其中包含 2 个 e 。
示例 3:
输入:s = "bcbcbc"
输出:6
解释:这个示例中,字符串 "bcbcbc" 本身就是最长的,因为所有的元音 a,e,i,o,u 都出现了 0 次。
"""
class Solution:
def findTheLongestSubstring(self, s: str) -> int:
"""
我们可以借助前缀和来表示元音字母奇偶
pre[i]][k]表示字符串前i个字符,第k个元音字母出现的个数
[l ,r]区间,转化为pre[r][k] - pre[l-1][k]
又因为元音字母出现了偶数次,而奇数-奇数,偶数-偶数 为偶数
所以,两个前缀和的奇偶性是确定的,即两个前缀和的奇偶性一样
而五个元音字母表示奇偶性,只有两个状态,我们想到用五位二进制数来表示
0表示奇数,1表示偶数
5个二进制数能表示32个状态
因此我们又用32大小数组,来存储每个状态对应的位置
:param s:
:return:
"""
ans, status, n = 0, 0, len(s)
pos = [-1]*(1<<5)
pos[0] = 0
for i in range(n):
if s[i] == 'a':
status ^= 1<<0
elif s[i] == 'e':
status ^= 1<<1
elif s[i] == 'i':
status ^= 1<<2
elif s[i] == 'o':
status ^= 1<<3
elif s[i] == 'u':
status ^= 1<<4
if pos[status] != -1:
ans = max(ans, i+1-pos[status])
else:
pos[status] = i + 1
return ans