📌  相关文章
📜  每个字符出现偶数次的子串数(1)

📅  最后修改于: 2023-12-03 15:40:39.572000             🧑  作者: Mango

每个字符出现偶数次的子串数

在字符串中找出所有满足每个字符出现次数均为偶数的子串数目。

例如,在字符串 "abcab" 中,满足条件的子串有 "a", "b", "c", "ab", "bc" 和 "cab" 共 $6$ 个。

思路

本题可以使用简单的数学方法来解决,即计算每个子串中每个字符出现的次数,并判断是否均为偶数。

具体来说,可以使用一个长度为 $n$ 的整数数组 $count$ 记录每个字符在子串中出现的次数。遍历所有子串并计算字符出现次数的复杂度为 $O(n^2)$,而判断是否为偶数则只需要遍历一次 $count$ 数组,复杂度为 $O(k)$($k$ 为字符集大小,本题中 $k=26$)。因此总时间复杂度为 $O(n^2k)$。

另一种解法是将问题转化为异或和的形式。对于一个子串 $[l,r]$,定义 $s_i$ 为从左往右第 $i$ 个字符在子串中出现的次数的奇偶性($s_i=0$ 表示出现偶数次,$s_i=1$ 表示出现奇数次)。那么子串中每个字符出现次数均为偶数的充要条件是所有 $s_i$ 的异或和为 $0$。因此可以遍历所有子串并计算其异或和,用哈希表记录每个异或和出现的次数即可。时间复杂度为 $O(nk)$。

代码

以下是第二种解法的代码(Python 3 实现):

def countSubstrings(s: str) -> int:
    n = len(s)
    count = defaultdict(int)
    count[0] = 1  # 空串的异或和为 0
    res, xor = 0, 0
    for i in range(n):
        xor ^= 1 << (ord(s[i]) - ord('a'))
        res += count[xor]
        for j in range(26):
            res += count[xor ^ (1 << j)]
        count[xor] += 1
    return res

其中 xor 记录当前子串的异或和,count 为哈希表,记录每个异或和出现的次数。由于 Python 中默认的哈希表(dict)不支持默认值,因此使用了 defaultdict