Welcome to Subscribe On Youtube
Formatted question description: https://leetcode.ca/all/1915.html
1915. Number of Wonderful Substrings
Level
Medium
Description
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 <= 10^5
word
consists of lowercase English letters from'a'
to'j'
.
Solution
Use bit manipulation. The number of occurrences of each letter can be represented as a bit such that 1 represents an odd number of times and 0 represents an even number of times. For ten letters, the value can be represented with ten bits, in range [0, 1023]. Loop over word
and for each index, get the value at the index and update the map, which stores each value’s number of occurrences (here “values” means “keys” of the map). Then loop over all pairs in the map such that the two keys have at most 1 bit that is different, and calculate the number of wonderful substrings.
-
class Solution { public long wonderfulSubstrings(String word) { long wonderful = 0; final int TOTAL = 1 << 10; long[] map = new long[TOTAL]; map[0] = 1L; int value = 0; int length = word.length(); for (int i = 0; i < length; i++) { char c = word.charAt(i); int index = c - 'a'; value ^= (1 << index); map[value]++; } for (int i = 0; i < TOTAL; i++) { wonderful += map[i] * (map[i] - 1) / 2; for (int j = 1; j <= i; j <<= 1) { if ((i & j) == j) wonderful += map[i] * map[i - j]; } } return wonderful; } } ############ class Solution { public long wonderfulSubstrings(String word) { int[] counter = new int[1 << 10]; counter[0] = 1; int state = 0; long ans = 0; for (char c : word.toCharArray()) { state ^= (1 << (c - 'a')); ans += counter[state]; for (int i = 0; i < 10; ++i) { ans += counter[state ^ (1 << i)]; } ++counter[state]; } return ans; } }
-
class Solution: def wonderfulSubstrings(self, word: str) -> int: counter = Counter({0: 1}) state = 0 ans = 0 for c in word: state ^= 1 << (ord(c) - ord('a')) ans += counter[state] for i in range(10): ans += counter[state ^ (1 << i)] counter[state] += 1 return ans ############ # 1915. Number of Wonderful Substrings # https://leetcode.com/problems/number-of-wonderful-substrings class Solution: def wonderfulSubstrings(self, word: str) -> int: count = [1] + [0] * 1023 curr = res = 0 for x in word: curr ^= (1 << ord(x) - ord('a')) res += count[curr] for bit in range(10): delta = 1 << bit res += count[curr ^ delta] count[curr] += 1 return res
-
class Solution { public: long long wonderfulSubstrings(string word) { vector<int> counter(1024); counter[0] = 1; long long ans = 0; int state = 0; for (char c : word) { state ^= (1 << (c - 'a')); ans += counter[state]; for (int i = 0; i < 10; ++i) ans += counter[state ^ (1 << i)]; ++counter[state]; } return ans; } };
-
func wonderfulSubstrings(word string) int64 { counter := make([]int, 1024) counter[0] = 1 state := 0 var ans int64 for _, c := range word { state ^= (1 << (c - 'a')) ans += int64(counter[state]) for i := 0; i < 10; i++ { ans += int64(counter[state^(1<<i)]) } counter[state]++ } return ans }
-
/** * @param {string} word * @return {number} */ var wonderfulSubstrings = function (word) { let counter = new Array(1 << 10).fill(0); counter[0] = 1; let state = 0; let ans = 0; for (let c of word) { state ^= 1 << (c.charCodeAt(0) - 'a'.charCodeAt(0)); ans += counter[state]; for (let i = 0; i < 10; ++i) { ans += counter[state ^ (1 << i)]; } ++counter[state]; } return ans; };
-
function wonderfulSubstrings(word: string): number { const cnt: number[] = new Array(1 << 10).fill(0); cnt[0] = 1; let ans = 0; let st = 0; for (const c of word) { st ^= 1 << (c.charCodeAt(0) - 'a'.charCodeAt(0)); ans += cnt[st]; for (let i = 0; i < 10; ++i) { ans += cnt[st ^ (1 << i)]; } cnt[st]++; } return ans; }