限制:
- 1 <= s.length <= 5 x 10^5
- s 只包含小写英文字母。
算法:
- 我们只需要关注 5 个字母的奇偶性,所以可以用一个长度为 2^5 的掩码表示闭区间 [0, i] 的状态。
- 维护一个哈希表,存储第一次出现这个掩码的位置。
- 线性扫描时,对于当前的一个掩码,用 i 减去第一次出现这个掩码的位置,就能得到一个以 i 结尾的极大子区间
时间复杂度
- 每个位置仅遍历一次,掩码和哈希表更新查询的时间都是常数,故总时间复杂度为 O(n)O(n)
class Solution {
public:
int findTheLongestSubstring(string s) {
int n = s.length();
const char c[5] = {'a', 'e', 'i', 'o', 'u'};
vector<int> h(32, n + 1);
h[0] = -1;
int ans = 0;
int mask = 0;
for (int i = 0; i < n; ++i) {
for (int j = 0; j < 5; ++j)
if (s[i] == c[j])
mask ^= 1 << j;
ans = max(ans, i - h[mask]);
h[mask] = min(h[mask], i);
}
return ans;
}
};