{x}
blog image

Sum of Beauty of All Substrings

The beauty of a string is the difference in frequencies between the most frequent and least frequent characters.

  • For example, the beauty of "abaacc" is 3 - 1 = 2.

Given a string s, return the sum of beauty of all of its substrings.

 

Example 1:

Input: s = "aabcb"
Output: 5
Explanation: The substrings with non-zero beauty are ["aab","aabc","aabcb","abcb","bcb"], each with beauty equal to 1.

Example 2:

Input: s = "aabcbaa"
Output: 17

 

Constraints:

  • 1 <= s.length <= 500
  • s consists of only lowercase English letters.

Solution Explanation:

This problem asks to calculate the sum of beauty values for all substrings of a given string. The beauty of a string is defined as the absolute difference between the maximum and minimum frequencies of its characters.

There are two main approaches to solve this problem:

Approach 1: Enumeration and Counting

This approach iterates through all possible substrings and counts the frequency of each character in each substring. Then, it calculates the beauty of the substring and adds it to the total sum.

  • Algorithm:

    1. Initialize ans to 0. This variable will store the total sum of beauty values.
    2. Iterate through each starting index i of the string.
    3. For each starting index i, iterate through each ending index j from i to the end of the string. This generates all substrings starting at i.
    4. For each substring, create a frequency counter (e.g., a dictionary or hashmap) to count the occurrences of each character.
    5. Find the maximum and minimum frequencies from the frequency counter.
    6. Calculate the beauty as max_freq - min_freq.
    7. Add the beauty to ans.
    8. Return ans.
  • Time Complexity: O(n^3), where n is the length of the string. This is because there are O(n^2) substrings, and for each substring, we need O(n) time to count character frequencies in the worst case.

  • Space Complexity: O(n) in the worst case to store the frequency counter for a substring. (Could be reduced to O(1) if using a fixed size array for the alphabet).

Approach 2: Optimized Counting

This approach improves upon the first approach by optimizing the frequency counting. It maintains a frequency map and updates it incrementally as we move from one substring to the next.

  • Algorithm:

    1. Initialize ans to 0.
    2. Iterate through each starting index i of the string.
    3. Initialize a frequency counter cnt and a frequency of frequencies counter freq. freq counts how many characters have each frequency.
    4. Iterate through each ending index j from i to the end of the string.
    5. For each character in the current substring, decrement the count in freq for its current frequency and increment it for the new frequency (after adding 1).
    6. Find the minimum frequency mi (the smallest frequency with a count > 0) and the maximum frequency mx.
    7. Calculate the beauty as mx - mi and add it to ans.
    8. Return ans.
  • Time Complexity: O(n^2), where n is the length of the string. This is because there are O(n^2) substrings, and for each substring, updating the frequency counters takes constant time on average.

  • Space Complexity: O(1), assuming the alphabet size is constant (26 in this case).

Code Examples:

The code examples in the problem description demonstrate both approaches. Approach 1 is simpler to understand but less efficient. Approach 2 is more complex but significantly faster. The complexities stated above are for Approach 1. Approach 2 has a time complexity of O(n^2). Both are given in multiple programming languages. Note that the constant factors and actual performance will vary depending on language, implementation details and input data. The Python3 example below is using the collections.Counter object which handles frequency counting efficiently.

Python3 (Approach 1 - less efficient):

from collections import Counter
 
class Solution:
    def beautySum(self, s: str) -> int:
        ans, n = 0, len(s)
        for i in range(n):
            cnt = Counter()
            for j in range(i, n):
                cnt[s[j]] += 1
                ans += max(cnt.values()) - min(cnt.values()) if len(cnt) > 0 else 0 #Handle empty substring case.
        return ans

Python3 (Approach 2 - more efficient):

from collections import Counter
 
class Solution:
    def beautySum(self, s: str) -> int:
        ans, n = 0, len(s)
        for i in range(n):
            cnt = Counter()
            freq = Counter()
            mi = mx = 1
            for j in range(i, n):
                freq[cnt[s[j]]] -= 1
                cnt[s[j]] += 1
                freq[cnt[s[j]]] += 1
 
                if cnt[s[j]] == 1:
                    mi = 1
                if freq[mi] == 0:
                    mi += 1
                if cnt[s[j]] > mx:
                    mx = cnt[s[j]]
 
                ans += mx - mi
        return ans
 

The other language examples in the problem description follow a similar structure to these Python examples, reflecting the two approaches. Remember to choose the appropriate approach based on the performance requirements of your application. For larger inputs, Approach 2 will be significantly faster.