Find Longest Awesome Substring
Jul 5, 2021
Given a string s
. An awesome substring is a non-empty substring of s
such that we can make any number of swaps in order to make it palindrome.
Return the length of the maximum length awesome substring of s
.
Example 1:
Input: s = "3242415"
Output: 5
Explanation: "24241" is the longest awesome substring, we can form the palindrome "24142" with some swaps.
Example 2:
Input: s = "12345678"
Output: 1
Example 3:
Input: s = "213123"
Output: 6
Explanation: "213123" is the longest awesome substring, we can form the palindrome "231132" with some swaps.
Example 4:
Input: s = "00"
Output: 2
Constraints:
1 <= s.length <= 10^5
s
consists only of digits.
Basic Idea:
这道题目和Number of Wonderful Substrings 比较接近。因为数字的范围只有0-9,而且只考虑奇偶次数,我们可以用一个mask来表示任意一个substring中每个数字奇偶次数的状态。我们用一个HashMap来存放之前出现过的mask,更新当前index i左边部分的mask,如果前面出现过相同的mask,则说明中间部分所有数字出现均为even,如果前面出现过和当前mask相差1bit的mask,则说明中间部分只有1个字母是odd。所以总时间复杂度为 O(10N)
.
Java Code:
class Solution {
public int longestAwesome(String s) {
// 存放每个mask对应的最早出现的右边界index
HashMap<Integer, Integer> prefixMaskIndexMap = new HashMap<>();
prefixMaskIndexMap.put(0, -1); // 处理从头开始match的情况
int mask = 0; // [0,i] 的mask
int maxLen = 0;
for (int i = 0; i < s.length(); ++i) {
mask ^= 1 << (s.charAt(i) - '0');
Integer prev = prefixMaskIndexMap.get(mask);
if (prev != null) {// 和前面出现过的mask相等,表示中间这段每个数字都出现even次
maxLen = Math.max(maxLen, i - prev);
}
for (int j = 0; j < 10; ++j) {// 相差一个bit,表示只有一个数字是odd次
prev = prefixMaskIndexMap.get(mask ^ (1 << j));
if (prev != null) {
maxLen = Math.max(maxLen, i - prev);
}
}
// 确保每个mask只存放最左边的
if (!prefixMaskIndexMap.containsKey(mask)) {
prefixMaskIndexMap.put(mask, i);
}
}
return maxLen;
}
}
Last updated