{x}
blog image

Maximum Score From Removing Substrings

You are given a string s and two integers x and y. You can perform two types of operations any number of times.

  • Remove substring "ab" and gain x points.
    • For example, when removing "ab" from "cabxbae" it becomes "cxbae".
  • Remove substring "ba" and gain y points.
    • For example, when removing "ba" from "cabxbae" it becomes "cabxe".

Return the maximum points you can gain after applying the above operations on s.

 

Example 1:

Input: s = "cdbcbbaaabab", x = 4, y = 5
Output: 19
Explanation:
- Remove the "ba" underlined in "cdbcbbaaabab". Now, s = "cdbcbbaaab" and 5 points are added to the score.
- Remove the "ab" underlined in "cdbcbbaaab". Now, s = "cdbcbbaa" and 4 points are added to the score.
- Remove the "ba" underlined in "cdbcbbaa". Now, s = "cdbcba" and 5 points are added to the score.
- Remove the "ba" underlined in "cdbcba". Now, s = "cdbc" and 5 points are added to the score.
Total score = 5 + 4 + 5 + 5 = 19.

Example 2:

Input: s = "aabbaaxybbaabb", x = 5, y = 4
Output: 20

 

Constraints:

  • 1 <= s.length <= 105
  • 1 <= x, y <= 104
  • s consists of lowercase English letters.

Solution Explanation: 1717. Maximum Score From Removing Substrings

This problem involves finding the maximum score achievable by removing substrings "ab" and "ba" from a given string, with different scores assigned to each. The optimal strategy is greedy: prioritize removing the substring that yields a higher score.

Approach:

  1. Greedy Strategy: We first determine which substring ("ab" or "ba") yields a higher score. We prioritize removing this higher-scoring substring first. This is because removing one substring might create opportunities to remove more of the same type of substring.

  2. Iteration: We iterate through the string. If we encounter the first character of the higher-scoring substring, we push it onto a stack. If we encounter the second character of the higher-scoring substring, and the stack's top element is the first character, we pop the top element from the stack (representing removing the higher-scoring substring) and update our score. Otherwise, we push the character onto the stack.

  3. Handling the Other Substring: After processing the higher-scoring substring, we repeat the process for the other substring. We iterate through the remaining string (represented by the stack) and remove the lower-scoring substrings.

  4. Score Calculation: The total score is the sum of scores obtained from removing both types of substrings.

Time and Space Complexity:

  • Time Complexity: O(n), where n is the length of the string. We iterate through the string at most twice (once for each substring). Stack operations (push and pop) take constant time.
  • Space Complexity: O(n) in the worst case, as the stack can potentially store all the characters of the string if no substrings are removed.

Code (Python):

def maximumGain(s, x, y):
    """
    Calculates the maximum score by removing substrings "ab" and "ba".
 
    Args:
        s: The input string.
        x: The score for removing "ab".
        y: The score for removing "ba".
 
    Returns:
        The maximum score achievable.
    """
 
    def remove_substring(stack, char1, char2, score):
        new_stack = []
        count = 0
        for char in stack:
            if new_stack and new_stack[-1] == char1 and char == char2:
                new_stack.pop()
                count += 1
            else:
                new_stack.append(char)
        return new_stack, count * score
 
    stack = list(s)
    
    if x > y:
        stack, count_x = remove_substring(stack, 'a', 'b', x)
        stack, count_y = remove_substring(stack, 'b', 'a', y)
    else:
        stack, count_y = remove_substring(stack, 'b', 'a', y)
        stack, count_x = remove_substring(stack, 'a', 'b', x)
 
 
    return count_x + count_y
 

Code (JavaScript):

function maximumGain(s, x, y) {
    const removeSubstring = (stack, char1, char2, score) => {
        const newStack = [];
        let count = 0;
        for (const char of stack) {
            if (newStack.length > 0 && newStack[newStack.length - 1] === char1 && char === char2) {
                newStack.pop();
                count++;
            } else {
                newStack.push(char);
            }
        }
        return [newStack, count * score];
    };
 
    let stack = s.split("");
 
    if (x > y) {
        [stack, let countX] = removeSubstring(stack, 'a', 'b', x);
        [stack, let countY] = removeSubstring(stack, 'b', 'a', y);
    } else {
        [stack, let countY] = removeSubstring(stack, 'b', 'a', y);
        [stack, let countX] = removeSubstring(stack, 'a', 'b', x);
    }
 
    return countX + countY;
}

The JavaScript and Python code demonstrate the same approach, prioritizing the higher-scoring substring removal. The remove_substring or removeSubstring function efficiently handles the removal process using a stack. The overall solution is clear, concise, and optimized for performance.