给你一个字符串 s
。请返回 s
中最长的 超赞子字符串 的长度。
「超赞子字符串」需满足满足下述两个条件:
- 该字符串是
s
的一个非空子字符串 - 进行任意次数的字符交换后,该字符串可以变成一个回文字符串
示例 1:
输入:s = "3242415" 输出:5 解释:"24241" 是最长的超赞子字符串,交换其中的字符后,可以得到回文 "24142"
示例 2:
输入:s = "12345678" 输出:1
示例 3:
输入:s = "213123" 输出:6 解释:"213123" 是最长的超赞子字符串,交换其中的字符后,可以得到回文 "231132"
示例 4:
输入:s = "00" 输出:2
提示:
1 <= s.length <= 10^5
s
仅由数字组成
提示 1
Given the character counts, under what conditions can a palindrome be formed ?
提示 2
From left to right, use bitwise xor-operation to compute for any prefix the number of times modulo 2 of each digit. (mask ^= (1<<(s[i]-'0')).
提示 3
Expected complexity is O(n*A) where A is the alphabet (10).
解法:状态压缩 + 哈希表
我们首先分析一下「超赞子字符串」的性质:
对于字符串 s 中的一个子串 s′ ,如果其中的字符能以某种顺序组成一个回文串,那么该串就是一个「超赞子字符串」。
这就表明,s′ 中最多只有一个字符出现了奇数次,其余的所有字符都出现了偶数次。这是因为对于任意一个回文串,如果它的回文中心是单个字符(例如 abcba),回文中心的字符出现了奇数次,其余的所有字符根据对称性出现了偶数次;如果它的回文中心是两个相同的字符(例如 abccba),那么所有字符根据对称性都出现了偶数次。
因此,对于任意一个子串 s′ 而言,我们只需要关系它的每一个字符出现了奇数次还是偶数次。由于字符串 s 中仅包含字符 0 到 9,因此我们可以用一个长度为 10 的 0−1 序列来表示任意一个子串 s′ 的状态。该 0−1 序列从低到高的第 i 位对应着 s′ 中出现字符 i 的奇偶性:具体地,0 对应着出现了偶数次,1 对应着出现了奇数次。
关于同类题型详解请见:LeetCode 1371. 每个元音包含偶数次的最长子字符串-CSDN博客
Java版:
class Solution {
public int longestAwesome(String s) {
int n = s.length();
int ans = 0;
int status = 0;
int[] pos = new int[1 << 10];
Arrays.fill(pos, -1);
pos[0] = 0;
for (int i = 0; i < n; i++) {
status ^= 1 << (s.charAt(i) - '0');
if (pos[status] >= 0) {
ans = Math.max(ans, i + 1 - pos[status]);
} else {
pos[status] = i + 1;
}
for (int j = 0; j <= 9; j++) {
int tmp = status ^ (1 << j);
if (pos[tmp] >= 0) {
ans = Math.max(ans, i + 1 - pos[tmp]);
}
}
}
return ans;
}
}
Python3版:
class Solution:
def longestAwesome(self, s: str) -> int:
n = len(s)
ans = 0
status = 0
pos = [-1] * (1 << 10)
pos[0] = 0
for i, c in enumerate(s):
status ^= 1 << int(c)
if pos[status] >= 0:
ans = max(ans, i + 1 - pos[status])
else:
pos[status] = i + 1
for j in range(10):
tmp = status ^ (1 << j)
if pos[tmp] >= 0:
ans = max(ans, i + 1 - pos[tmp])
return ans
复杂度分析
时间复杂度:O(n*A),其中 n 是字符串 s 的长度,A 表示字符集,在本题中字符串只包含 10 个数字字符,A=10。
空间复杂度:O(2^A),即为哈希映射使用的空间。A表示 10 个数字字符压缩成一个状态数的最大值,在本题中 A=10。我们需要对应 2^10 即 1024 大小的空间来存放每个状态第一次出现的位置.