最美子字符串的数目
难度:
标签:
题目描述
代码结果
运行时间: 803 ms, 内存: 17.0 MB
/*
* 思路:
* 1. 利用Java Stream API进行流式处理。
* 2. 和普通Java代码思路一样,只是在处理过程中使用Stream进行处理。
*/
import java.util.HashMap;
import java.util.stream.IntStream;
public class BeautifulSubstringsStream {
public int countBeautifulSubstrings(String word) {
int[] prefixOddEven = new int[10];
HashMap<Integer, Integer> map = new HashMap<>();
final int[] currentState = {0};
final int[] result = {0};
map.put(0, 1); // 初始化前缀状态0的出现次数
IntStream.range(0, word.length()).forEach(i -> {
int index = word.charAt(i) - 'a';
prefixOddEven[index] ^= 1; // 更新前缀状态
currentState[0] = 0;
for (int j = 0; j < 10; j++) {
currentState[0] |= (prefixOddEven[j] << j); // 计算当前前缀状态
}
result[0] += map.getOrDefault(currentState[0], 0);
map.put(currentState[0], map.getOrDefault(currentState[0], 0) + 1);
});
return result[0];
}
public static void main(String[] args) {
BeautifulSubstringsStream bss = new BeautifulSubstringsStream();
System.out.println(bss.countBeautifulSubstrings("aba")); // 4
System.out.println(bss.countBeautifulSubstrings("aabb")); // 9
System.out.println(bss.countBeautifulSubstrings("he")); // 2
}
}
解释
方法:
这个题解使用了位运算和前缀XOR的概念来高效地解决问题。首先,每个字母可以映射到一个10位的二进制数中的某一位(因为字母'a'到'j'共有10个)。对于字符串中的每个字符,通过一个异或操作更新当前的前缀XOR值。这个前缀XOR在二进制表示中,每位的1表示对应位置的字母出现奇数次。题解中使用了一个字典来存储每个前缀XOR出现的次数。然后,计算所有可能的最美子字符串的数量。只要当前的前缀XOR或者与之前某个前缀XOR的差异正好是一位(即异或结果中只有一个位是1),则表示这之间的子字符串是最美的。总体上,此方法避免了直接检查每个子字符串,而是通过巧妙地利用前缀XOR来统计满足条件的子字符串数量。
时间复杂度:
O(n + K^2),其中K是唯一前缀XOR值的数量,最坏情况下K为1024
空间复杂度:
O(K),其中K为前缀XOR的不同值的数量,最坏情况下为1024
代码细节讲解
🦆
在位运算方法中,每个字母映射到一个10位二进制数的具体位是如何决定的?为什么选择异或操作来更新前缀XOR值?
▷🦆
题解提到的`如果当前的前缀XOR或者与之前某个前缀XOR的差异正好是一位`,这里的逻辑是否确保了子字符串的最美条件,即至多一个字母出现奇数次?
▷🦆
在实际应用中,如何处理和优化大量重复的前缀XOR值,以避免不必要的重复计算和存储?
▷