Number of Wonderful Substrings

Updated on 20 June, 2025
Number of Wonderful Substrings header image

Problem Statement

In this problem, we are introduced to the concept of a wonderful string. A string is considered wonderful if at most one character in the string appears an odd number of times. For example, the strings "ccjjc" and "abab" both qualify as wonderful because either no letter or exactly one letter appears an odd number of times in them.

Given a specific string word composed solely of the first ten lowercase English letters (from 'a' to 'j'), our task is to determine how many non-empty substrings of word are wonderful. It is important to note that if identical substrings occur multiple times in word, each occurrence is counted separately.

A substring is defined as a contiguous sequence of characters within a string. This problem requires assessing each possible substring of word and counting how many of those satisfy the wonderful condition.

Examples

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:
- "**h**e" -> "h"
  • "he" -> "e"

Constraints

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

Approach and Intuition

To solve this problem, let's break down the challenge using the provided examples:

  1. For each substring, we need to verify if it can be considered wonderful. This involves counting the frequency of each character and checking if at most only one character has an odd count.

  2. To efficiently explore all possible substrings of word, understanding the constraints is crucial:

    • word length is up to 105, suggesting that a naive approach, which might require examining all substrings, could be too slow. Specifically, as there are potentially over 5,000,000 substrings, naive frequency counting for each could be inefficient.
  3. An insightful approach involves using bitwise operations:

    • Keep a frequency mask, where each bit represents the odd/even status of character counts from 'a' to 'j'. This bitwise representation (odd-even status mask) helps in quickly understanding how the addition of a character affects the wonderful property of a substring.
    • Iterate over the string and update this mask as you expand substrings. Use this mask to check if the substring formed by extending to the current character maintains a wonderful state (only one or zero bits set).
  4. Using hash tables or arrays to store intermediate results, such as the number of times each mask appears, can significantly cut down redundant calculations, enabling us to compute results faster.

By following this technique, every substring's wonderful nature is evaluated indirectly through the update of the mask, making the process much quicker and computationally feasible even for large strings. Each step essentially adjusts or checks the bit corresponding to a character in linear time relative to the string length with constant extra space relative to the character set size, leading to efficient overall performance.

Solutions

  • Java
  • Python
java
class Solution {
    public long countWonderfulSubstrings(String text) {
        int length = text.length();

        Map<Integer, Integer> countMap = new HashMap<>();
        countMap.put(0, 1);

        int currentMask = 0;
        long totalCount = 0L;
        for (int j = 0; j < length; j++) {
            char ch = text.charAt(j);
            int bitIndex = ch - 'a';

            currentMask ^= (1 << bitIndex);
            
            totalCount += countMap.getOrDefault(currentMask, 0);
            countMap.put(currentMask, countMap.getOrDefault(currentMask, 0) + 1);

            for (int b = 0; b < 10; b++) {
                totalCount += countMap.getOrDefault(currentMask ^ (1 << b), 0);
            }
        }
        return totalCount;
    }
}

The "Number of Wonderful Substrings" function in Java counts the number of "wonderful" substrings in a given string. Here's a breakdown of how the method works:

  • Initialize a HashMap (countMap) to keep track of encountered bitmask frequencies, starting with the mapping of 0 to 1.
  • Use an integer currentMask to represent the current character bitmask as the string is processed.
  • Traverse each character in the input string:
    • Convert the character to its corresponding bitmask index.
    • Update currentMask using XOR to toggle the bits.
    • Increment the totalCount of wonderful substrings:
      • Directly add the number of times currentMask has been encountered so far.
      • Search for previously encountered masks that differ by exactly one bit, leveraging XOR, and add their counts to totalCount.
    • Update countMap for the currentMask to reflect the latest count.

The function efficiently counts possible substrings with the property that all characters occur an even number of times or all except one character occur an even number of times by using bit manipulation and a hash map to track and compute results dynamically. The use of XOR allows for toggling character counts in the bitmask, providing a compact and fast way to manage state as the function processes each character in the string.

python
class Solution(object):
    def countWonderfulSubstrings(self, text):
        count_map = {}
        count_map[0] = 1

        bitmask = 0
        total = 0
        for char in text:
            bit_index = ord(char) - 97
            bitmask ^= (1 << bit_index)

            if bitmask in count_map:
                total += count_map[bitmask]
                count_map[bitmask] += 1
            else:
                count_map[bitmask] = 1

            for i in range(10):
                altered_mask = bitmask ^ (1 << i)
                if altered_mask in count_map:
                    total += count_map[altered_mask]

        return total

This Python3 solution tackles the problem of counting the number of wonderful substrings within a given string. A "wonderful" substring is defined by having at most one character that appears an odd number of times. The program uses a bitmask to efficiently track the count of characters and their odd/even nature.

  • Initialize a dictionary count_map to store the occurrences of each bitmask configuration, setting the count of bitmask 0 (no characters appear an odd number of times) to 1.
  • Start with a bitmask set to 0, and a counter total for the wonderful substrings found.

For each character in the input string text:

  • Calculate bit_index as the position of the character in the alphabet (0 for 'a', 1 for 'b', etc.).
  • Update the bitmask using an XOR operation at that character's bit index. This toggles the bit between 0 (even occurrences) and 1 (odd occurrences).
  • If this bitmask exists in count_map, increment total by the stored count and update the count of this bitmask in count_map.
  • If not, add this new bitmask to count_map with a count of 1.
  • Iterate through each possible single bit alteration of the bitmask (representing every odd character count scenario). If such an altered mask is found in count_map, increase total by the occurrences of that configuration.

Finally, the function returns total, the count of all wonderful substrings found in the input string. This approach is efficient, using bit manipulation to track character occurrences and the properties of wonderful substrings without resorting to brute force substring enumeration.

Comments

No comments yet.