加载中...
1915-最美子字符串的数目(Number of Wonderful Substrings)
发表于:2021-12-03 | 分类: 中等
字数统计: 530 | 阅读时长: 2分钟 | 阅读量:

原文链接: https://leetcode-cn.com/problems/number-of-wonderful-substrings

英文原文

A wonderful string is a string where at most one letter appears an odd number of times.

  • For example, "ccjjc" and "abab" are wonderful, but "ab" is not.

Given a string word that consists of the first ten lowercase English letters ('a' through 'j'), return the number of wonderful non-empty substrings in word. If the same substring appears multiple times in word, then count each occurrence separately.

A substring is a contiguous sequence of characters in a string.

 

Example 1:

Input: word = "aba"
Output: 4
Explanation: The four wonderful substrings are underlined below:
- "aba" -> "a"
- "aba" -> "b"
- "aba" -> "a"
- "aba" -> "aba"

Example 2:

Input: word = "aabb"
Output: 9
Explanation: The nine wonderful substrings are underlined below:
- "aabb" -> "a"
- "aabb" -> "aa"
- "aabb" -> "aab"
- "aabb" -> "aabb"
- "aabb" -> "a"
- "aabb" -> "abb"
- "aabb" -> "b"
- "aabb" -> "bb"
- "aabb" -> "b"

Example 3:

Input: word = "he"
Output: 2
Explanation: The two wonderful substrings are underlined below:
- "he" -> "h"
- "he" -> "e"

 

Constraints:

  • 1 <= word.length <= 105
  • word consists of lowercase English letters from 'a' to 'j'.

中文题目

如果某个字符串中 至多一个 字母出现 奇数 次,则称其为 最美 字符串。

  • 例如,"ccjjc""abab" 都是最美字符串,但 "ab" 不是。

给你一个字符串 word ,该字符串由前十个小写英文字母组成('a''j')。请你返回 word最美非空子字符串 的数目如果同样的子字符串在 word 中出现多次,那么应当对 每次出现 分别计数

子字符串 是字符串中的一个连续字符序列。

 

示例 1:

输入:word = "aba"
输出:4
解释:4 个最美子字符串如下所示:
- "aba" -> "a"
- "aba" -> "b"
- "aba" -> "a"
- "aba" -> "aba"

示例 2:

输入:word = "aabb"
输出:9
解释:9 个最美子字符串如下所示:
- "aabb" -> "a"
- "aabb" -> "aa"
- "aabb" -> "aab"
- "aabb" -> "aabb"
- "aabb" -> "a"
- "aabb" -> "abb"
- "aabb" -> "b"
- "aabb" -> "bb"
- "aabb" -> "b"

示例 3:

输入:word = "he"
输出:2
解释:2 个最美子字符串如下所示:
- "he" -> "h"
- "he" -> "e"

 

提示:

  • 1 <= word.length <= 105
  • word 由从 'a''j' 的小写英文字母组成

通过代码

高赞题解

由于我们只关心每个字母出现次数的奇偶性,因此可以将「字母出现次数」转换成「字母出现次数的奇偶性」,这可以用一个长为 $10$ 的二进制串表示,二进制串的第 $i$ 位为 $0$ 表示第 $i$ 个小写字母出现了偶数次,为 $1$ 表示第 $i$ 个小写字母出现了奇数次。

考虑字母出现次数的前缀和,由于只考虑奇偶性,我们也可以将其视作一个长为 $10$ 的二进制串。此时计算前缀和由加法运算改为异或运算,这是因为异或运算的本质是在模 $2$ 剩余系中进行加法运算,刚好对应奇偶性的变化。

若有两个不同下标的前缀和相同,则这两个前缀和的异或结果为 $0$,意味着这段子串的各个字母的个数均为偶数,符合题目要求。因此,我们可以在求前缀和的同时,用一个长为 $2^{10}=1024$ 的 $\textit{cnt}$ 数组统计每个前缀和二进制串出现的次数,从而得到相同前缀和的对数,即各个字母的个数均为偶数的子串个数。

题目还允许有一个字母出现奇数次,这需要我们寻找两个前缀和,其异或结果的二进制数中恰好有一个 $1$,意味着这段子串的各个字母的个数仅有一个为奇数。对此我们可以枚举当前前缀和的每个比特,将其反转,然后去 $\textit{cnt}$ 中查找该前缀和的出现次数。

将所有统计到的次数累加即为答案。时间复杂度为 $O(10\cdot n)$,$n$ 为字符串 $\textit{word}$ 的长度。

上面所说的技巧在前缀和的题目中经常用到,例如:

func wonderfulSubstrings(word string) int64 {
	cnt := [1024]int{1} // 初始前缀和为 0,需将其计入出现次数
	ans, pre := 0, 0
	for _, ch := range word {
		pre ^= 1 << (ch - 'a') // 计算当前前缀和
		ans += cnt[pre] // 所有字母均出现偶数次
		for i := 1; i < 1024; i <<= 1 { // 枚举其中一个字母出现奇数次
			ans += cnt[pre^i] // 反转第 i 个字母的出现次数的奇偶性
		}
		cnt[pre]++ // 更新前缀和出现次数
	}
	return int64(ans)
}

统计信息

通过次数 提交次数 AC比率
2999 7595 39.5%

提交历史

提交时间 提交结果 执行时间 内存消耗 语言
上一篇:
1914-循环轮转矩阵(Cyclically Rotating a Grid)
下一篇:
1901-找出顶峰元素 II(Find a Peak Element II)
本文目录
本文目录