LeetCode 1915. 最美子字符串的数目

1915. 最美子字符串的数目

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

  • 例如,"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 <= 10^5
  • word 由从 'a' 到 'j' 的小写英文字母组成

提示 1

For each prefix of the string, check which characters are of even frequency and which are not and represent it by a bitmask.


提示 2

Find the other prefixes whose masks differs from the current prefix mask by at most one bit.

解法:状态压缩 + 前缀数组

提示 1

如果字符串 word 的某个子串 word[i..j] 是最美字符串,那么其中最多只有一个字符出现奇数次,这说明:

对于任意一次字符 c 而言,word 的 i−1 前缀 word[0..i−1] 与 j 前缀 word[0..j] 中字符 c 的出现次数必须同奇偶。同时,我们最多允许有一个字符 c,它在两个前缀中出现次数的奇偶性不同。

提示 2

由于题目保证了 word 中只会包含前 10 个小写字母,因此我们可以用一个长度为 10 的二进制数 mask 表示 word 的前缀中 [a,j] 出现次数的奇偶性,其中 mask 的第 i 位为 1 表示第 i 个字母出现了奇数次,0 表示第 i 个字母出现了偶数次。

记 word 的 k 前缀 word[0..k] 对应的二进制数为 mask k ​ 。

根据提示 1,word[i..j] 是最美字符串,当且仅当 mask i−1 ​ 和 mask j ​ 的二进制表示最多只有一位不同。 特别地,如果 i=0,那么 mask −1 ​ =0,即所有字母均未出现过。

思路与算法

我们对字符串 word 进行一次遍历。 当我们遍历到 word[i] 时,我们首先计算出 mask i ​ ,再遍历 mask i ​ 的 10 个二进制位,将其翻转(从 0 变为 1 或者从 1 变为 0)得到 mask i ′ ​ 。

此时 mask i ​ 和 mask i ′ ​ 的二进制表示恰好有一位不同。

为了快速计算答案,我们需要使用一个哈希映射 freq 存储每一个 mask 出现的次数。

这样一来,我们直接将答案增加 freq[mask i ′ ​ ] 即可。

此外,我们还需要将答案增加 freq[mask i ​],即两个前缀出现字母的奇偶性完全相同。 

同类题型详解:LeetCode 1177. 构建回文串检测-CSDN博客

LeetCode 1371. 每个元音包含偶数次的最长子字符串-CSDN博客

LeetCode 1542. 找出最长的超赞子字符串-CSDN博客

Java版:

class Solution {
    public long wonderfulSubstrings(String word) {
        long ans = 0;
        int status = 0;
        int[] count = new int[1 << 10];
        count[0] = 1;
        for (int i = 0; i < word.length(); i++) {
            status ^= 1 << (word.charAt(i) - 'a');
            ans += count[status];
            for (int j = 0; j <= 9; j++) {
                int tmp = status ^ (1 << j);
                ans += count[tmp];
            }
            count[status]++;
        }
        return ans;
    }
}

Python3版:

class Solution:
    def wonderfulSubstrings(self, word: str) -> int:
        ans = 0
        mask = 0
        count = [0] * (1 << 10)
        count[0] = 1
        for c in word:
            mask ^= 1 << ord(c) - ord('a')
            ans += count[mask]
            for j in range(10):
                tmp = mask ^ (1 << j)
                ans += count[tmp]
            count[mask] += 1
        return ans

 

复杂度分析

  • 时间复杂度:O(n*A),其中 n 是字符串 s 的长度,A 表示字符集,在本题中字符串只包含 10 个字符,A=10。
  • 空间复杂度:O(2^A),即为哈希映射使用的空间。A表示 10 个字符压缩成一个状态数的最大值,在本题中 A=10。我们需要对应 2^10 即 1024 大小的空间来存放每个状态第一次出现的位置.

解法2:状态压缩 + 哈希表

Java版:

class Solution {
    public long wonderfulSubstrings(String word) {
        long ans = 0;
        int status = 0;
        Map<Integer, Integer> count = new HashMap<>();
        count.put(0, 1);
        for (int i = 0; i < word.length(); i++) {
            status ^= 1 << (word.charAt(i) - 'a');
            ans += count.getOrDefault(status, 0);
            for (int j = 0; j <= 9; j++) {
                int tmp = status ^ (1 << j);
                ans += count.getOrDefault(tmp, 0);
            }
            count.merge(status, 1, Integer::sum);
        }
        return ans;
    }
}

Python3版:

class Solution:
    def wonderfulSubstrings(self, word: str) -> int:
        ans = 0
        mask = 0
        count = {0: 1}
        for c in word:
            mask ^= 1 << ord(c) - ord('a')
            ans += count[mask] if mask in count else 0
            for j in range(10):
                tmp = mask ^ (1 << j)
                ans += count[tmp] if tmp in count else 0
            count[mask] = count[mask] + 1 if mask in count else 1
        return ans

复杂度分析

  • 时间复杂度:O(n*A),其中 n 是字符串 word 的长度,A 是字符集,在本题中 A=10。
  • 空间复杂度:O(min(n,2^A))。哈希映射中存储的键值对个数由字符串 word 的长度 n 以及 A 位二进制数的总数 2^A 共同限制,因此空间复杂度为 O(min(n,2^A))。
  • 15
    点赞
  • 24
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值