Open In App

Maximize cost obtained by removal of substrings "pr" or "rp" from a given String

Last Updated : 25 Apr, 2025
Comments
Improve
Suggest changes
Like Article
Like
Report

Given a string s consisting of lowercase English letters, in one operation, a substring "pr" can be removed from s to earn an amount x, or a substring "rp" can be removed from s to earn an amount y.
The task is to determine the maximum amount that can be earned by performing zero or more operations optimally.

Note: 

  • Substring of a string s is defined as a continuous sequence of characters in s.
  • After removing pr or rp, the order of remaining letters should remain the same.

Examples:

Input: str = “abppprrr”, x = 5, y = 4 
Output: 15 
Explanation: Following operations are performed: 
“abppprrr” -> “abpprr”, cost = 5 
“abpprr” -> “abpr”, cost = 10 
“abpr” -> “ab”, cost = 15 
Therefore, the maximized cost is 15

Input: str = “prprprrp”, x= 7, y = 10 
Output: 37

Approach - Greedy Method - O(n) time and O(1) space

The problem can be solved using a Greedy Approach. The idea is to remove "pr" if x is greater than y, or remove "rp" otherwise. The approach follows these steps:

1. If x < y, swap the values of x and y, and also replace characters 'p' with 'r' and vice versa in the given string.

2. Count Occurrences:

  • Initialize two variables, countP and countR, to store the count of 'p' and 'r' in the string respectively.

3. Iterate Over the String:

For each character in the string:

  • If the character is 'p', increment countP by 1.
  • If the character is 'r', check the value of countP:
    • If countP > 0, it means there's a previous 'p' that can be paired with this 'r' to remove "pr". In this case, increment the result by X and decrement countP by 1.
    • If countP == 0, increment countR by 1 because this 'r' cannot be paired with any previous 'p'.
  • If the character is neither 'p' nor 'r', increment the result by min(countP, countR) * Y. This handles the remaining unpaired 'p' and 'r' by removing "rp" pairs optimally.

4. Return the Result: After processing all characters, the result will contain the maximum amount earned.

C++
#include <iostream>
#include <string>
using namespace std;

bool swapXY(string& s, int x, int y)
{
    int n = s.length();

    // To maintain x >= y
    swap(x, y);

    for (int i = 0; i < n; i++) {
        // Replace 'p' to 'r'
        if (s[i] == 'p') {
            s[i] = 'r';
        }
        // Replace 'r' to 'p'.
        else if (s[i] == 'r') {
            s[i] = 'p';
        }
    }
}

// Function to return the maximum cost
int maxCost(string s, int x, int y)
{
    int n = s.length();

    // To maintain x >= y.
    if (y > x) {
        swapXY(s, x, y);
    }

    int res = 0;  
    int countP = 0;  
    int countR = 0;  

    for (int i = 0; i < n; i++) {
        if (s[i] == 'p') {
            countP++;
        }
        else if (s[i] == 'r') {
            
            // If substring "pr" is removed
            if (countP > 0) {
                countP--;
                res += x;
            }
            else {
                countR++;
            }
        }
        else {
            
            // If any substring "rp" left in the Stack
            res += min(countP, countR) * y;
            countP = 0;
            countR = 0;
        }
    }

    // If any substring "rp" left in the Stack
    res += min(countP, countR) * y;
    return res;
}

int main()
{
    string s = "abppprrr";  
    int x = 5, y = 4; 
    cout << maxCost(s, x, y);  
}
Java
import java.util.*;

public class GfG {
    public static void main(String[] args) {
        String s = "abppprrr";
        int x = 5, y = 4;
        System.out.println(maxCost(s, x, y));
    }

    // Function to swap 'p' and 'r'
    static void swapXY(StringBuilder s, int x, int y) {
        int n = s.length();

        // To maintain x >= y
        if (x < y) {
            int temp = x;
            x = y;
            y = temp;
        }

        for (int i = 0; i < n; i++) {
            // Replace 'p' to 'r'
            if (s.charAt(i) == 'p') {
                s.setCharAt(i, 'r');
            } else if (s.charAt(i) == 'r') {
                // Replace 'r' to 'p'
                s.setCharAt(i, 'p');
            }
        }
    }

    // Function to return the maximum cost
    static int maxCost(String s, int x, int y) {
        int n = s.length();

        // To maintain x >= y
        if (y > x) {
            StringBuilder sb = new StringBuilder(s);
            swapXY(sb, x, y);
            s = sb.toString();
        }

        int res = 0;
        int countP = 0;
        int countR = 0;

        for (int i = 0; i < n; i++) {
            if (s.charAt(i) == 'p') {
                countP++;
            } else if (s.charAt(i) == 'r') {
                // If substring "pr" is removed
                if (countP > 0) {
                    countP--;
                    res += x;
                } else {
                    countR++;
                }
            } else {
                // If any substring "rp" left in the Stack
                res += Math.min(countP, countR) * y;
                countP = 0;
                countR = 0;
            }
        }

        // If any substring "rp" left in the Stack
        res += Math.min(countP, countR) * y;
        return res;
    }
}
Python
def swapXY(s, x, y):
    n = len(s)

    # To maintain x >= y
    if x < y:
        x, y = y, x

    s = list(s)  
    for i in range(n):
        # Replace 'p' with 'r'
        if s[i] == 'p':
            s[i] = 'r'
        # Replace 'r' with 'p'
        elif s[i] == 'r':
            s[i] = 'p'
    return ''.join(s)  

# Function to return the maximum cost
def maxCost(s, x, y):
    n = len(s)

    # To maintain x >= y, swap if necessary
    if y > x:
        s = swapXY(s, x, y)

    res = 0
    countP = 0
    countR = 0

    # Iterate over the string
    for i in range(n):
        if s[i] == 'p':
            countP += 1  
        elif s[i] == 'r':
            
            # If substring 'pr' is removed
            if countP > 0:
                countP -= 1
                res += x 
            else:
                countR += 1  
        else:
            # Process remaining 'rp' substrings
            res += min(countP, countR) * y
            countP = 0  # Reset countP
            countR = 0  # Reset countR

    # Add the remaining "rp" pairs
    res += min(countP, countR) * y
    return res


s = 'abppprrr' 
x = 5           
y = 4         
print(maxCost(s, x, y))
C#
using System;
using System.Collections.Generic;

class GfG
{
    static void SwapXY(ref string s, ref int x, ref int y)
    {
        int n = s.Length;

        // To maintain x >= y
        if (x < y)
        {
            int temp = x;
            x = y;
            y = temp;
        }

        char[] arr = s.ToCharArray();
        for (int i = 0; i < n; i++) {
            // Replace 'p' to 'r'
            if (arr[i] == 'p') {
                arr[i] = 'r';
            }
            // Replace 'r' to 'p'.
            else if (arr[i] == 'r') {
                arr[i] = 'p';
            }
        }
        s = new string(arr);
    }

    // Function to return the maximum cost
    static int MaxCost(string s, int x, int y)
    {
        int n = s.Length;

        // To maintain x >= y.
        if (y > x) {
            SwapXY(ref s, ref x, ref y);
        }

        int res = 0;
        int countP = 0;
        int countR = 0;

        for (int i = 0; i < n; i++) {
            if (s[i] == 'p') {
                countP++;
            }
            else if (s[i] == 'r') {
                // If substring "pr" is removed
                if (countP > 0) {
                    countP--;
                    res += x;
                }
                else {
                    countR++;
                }
            }
            else {
                res += Math.Min(countP, countR) * y;
                countP = 0;
                countR = 0;
            }
        }

        // If any substring "rp" left in the Stack
        res += Math.Min(countP, countR) * y;
        return res;
    }

    static void Main()
    {
        string s = "abppprrr";
        int x = 5, y = 4;
        Console.WriteLine(MaxCost(s, x, y));
    }
}
JavaScript
function swapXY(s, x, y) {
    const n = s.length;

    // To maintain x >= y
    if (x < y) {
        [x, y] = [y, x];
    }

    let arr = s.split('');
    for (let i = 0; i < n; i++) {
        // Replace 'p' to 'r'
        if (arr[i] === 'p') {
            arr[i] = 'r';
        }
        // Replace 'r' to 'p'.
        else if (arr[i] === 'r') {
            arr[i] = 'p';
        }
    }
    return arr.join('');
}

// Function to return the maximum cost
function maxCost(s, x, y) {
    const n = s.length;

    // To maintain x >= y.
    if (y > x) {
        s = swapXY(s, x, y);
    }

    let res = 0;
    let countP = 0;
    let countR = 0;

    for (let i = 0; i < n; i++) {
        if (s[i] === 'p') {
            countP++;
        }
        else if (s[i] === 'r') {
            // If substring "pr" is removed
            if (countP > 0) {
                countP--;
                res += x;
            }
            else {
                countR++;
            }
        }
        else {
            // If any substring "rp" left in the Stack
            res += Math.min(countP, countR) * y;
            countP = 0;
            countR = 0;
        }
    }

    // If any substring "rp" left in the Stack
    res += Math.min(countP, countR) * y;
    return res;
}

const s = "abppprrr";
const x = 5, y = 4;
console.log(maxCost(s, x, y));

Output
15

Approach - Greedy Stack-based Pair Removal Approach - O(n) time and O(n) space

This approach uses a greedy strategy with a stack to process the string. It iterates through the string from right to left, removing pairs of "pr" or "rp" based on which pair has a higher value. The stack helps maintain the order of characters, and when a valid pair is found (either "pr" or "rp"), it is removed, and the corresponding value is added to the total. This process continues until all possible pairs are removed, maximizing the total amount earned.

Steps:

  1. First, we check either X is greater than Y or not if X > Y then removing "pr" will give us greater value and if Y > X then "rp" gives more.
  2. We should greedily remove "pr" or "rp" depending upon whether X is greater or Y is greater.
  3. We will be using a stack to keep the order same after removal of substrings.
  4. After removing all possible "pr" we will check in rest of the string if any "rp" present and we will remove them and vice versa.
C++
#include <iostream>
#include <stack>
#include <string>
using namespace std;

int maxCost(int x, int y, string s) {
    int answer = 0;

    // Setting up the priority of different pairs
    string a = "pr";
    string b = "rp";

    // Checking which pair has a higher priority
    if (x < y) {
        swap(x, y);
        swap(a, b);
    }

    stack<char> st;
    
    // Iterating through the input string from right to left
    for (int i = (int)s.size() - 1; i >= 0; i--) {
        // Checking if the current character and the top of the stack
        // form a valid pair and reducing the size of the stack and 
        // updating the answer accordingly
        if (st.size() > 0 && s[i] == a[0] && st.top() == a[1]) {
            st.pop();
            answer += x;
        } else {
            st.push(s[i]);
        }
    }

    // Emptying out the remaining characters in the stack
    s = "";
    while (st.size() > 0) {
        s.push_back(st.top());
        st.pop();
    }

    // Repeating the same process with the other type of pairs (if necessary)
    for (int i = (int)s.size() - 1; i >= 0; i--) {
        if (st.size() > 0 && s[i] == b[0] && st.top() == b[1]) {
            st.pop();
            answer += y;
        } else {
            st.push(s[i]);
        }
    }

    return answer;
}

int main() {
    string s = "abppprrr";  
    int x = 5, y = 4;       
    int answer = maxCost(x, y, s);  
    cout << answer << endl;
    return 0;
}
Java
import java.util.Stack;

public class GfG {
    public static int maxCost(int x, int y, String s) {
        int answer = 0;

        // Setting up the priority of different pairs
        String a = "pr";
        String b = "rp";

        // Checking which pair has a higher priority
        if (x < y) {
            int temp = x;
            x = y;
            y = temp;
            String tempStr = a;
            a = b;
            b = tempStr;
        }

        Stack<Character> st = new Stack<>();
        
        // Iterating through the input string from right to left
        for (int i = s.length() - 1; i >= 0; i--) {
            // Checking if the current character and the top of the stack
            // form a valid pair and reducing the size of the stack and 
            // updating the answer accordingly
            if (!st.isEmpty() && s.charAt(i) == a.charAt(0) && st.peek() == a.charAt(1)) {
                st.pop();
                answer += x;
            } else {
                st.push(s.charAt(i));
            }
        }

        // Emptying out the remaining characters in the stack
        s = "";
        while (!st.isEmpty()) {
            s = st.pop() + s;
        }

        // Repeating the same process with the other type of pairs (if necessary)
        for (int i = s.length() - 1; i >= 0; i--) {
            if (!st.isEmpty() && s.charAt(i) == b.charAt(0) && st.peek() == b.charAt(1)) {
                st.pop();
                answer += y;
            } else {
                st.push(s.charAt(i));
            }
        }

        return answer;
    }

    public static void main(String[] args) {
        String s = "abppprrr";
        int x = 5, y = 4;
        int answer = maxCost(x, y, s);
        System.out.println(answer);
    }
}
Python
def maxCost(x, y, s):
    answer = 0

    # Setting up the priority of different pairs
    a = "pr"
    b = "rp"

    # Checking which pair has a higher priority
    if x < y:
        x, y = y, x
        a, b = b, a

    st = []
    
    # Iterating through the input string from right to left
    for i in range(len(s) - 1, -1, -1):
        # Checking if the current character and the top of the stack
        # form a valid pair and reducing the size of the stack and 
        # updating the answer accordingly
        if st and s[i] == a[0] and st[-1] == a[1]:
            st.pop()
            answer += x
        else:
            st.append(s[i])

    # Emptying out the remaining characters in the stack
    s = ""
    while st:
        s += st.pop()

    # Repeating the same process with the other type of pairs (if necessary)
    for i in range(len(s) - 1, -1, -1):
        if st and s[i] == b[0] and st[-1] == b[1]:
            st.pop()
            answer += y
        else:
            st.append(s[i])

    return answer

# Main execution
s = "abppprrr"
x = 5
y = 4
answer = maxCost(x, y, s)
print(answer)
C#
// Importing necessary namespaces
using System;
using System.Collections.Generic;

class GfG {
    public static int maxCost(int x, int y, string s) {
        int answer = 0;

        // Setting up the priority of different pairs
        string a = "pr";
        string b = "rp";

        // Checking which pair has a higher priority
        if (x < y) {
            (x, y) = (y, x);
            (a, b) = (b, a);
        }

        Stack<char> st = new Stack<char>();
        
        // Iterating through the input string from right to left
        for (int i = s.Length - 1; i >= 0; i--) {
            // Checking if the current character and the top of the stack
            // form a valid pair and reducing the size of the stack and 
            // updating the answer accordingly
            if (st.Count > 0 && s[i] == a[0] && st.Peek() == a[1]) {
                st.Pop();
                answer += x;
            } else {
                st.Push(s[i]);
            }
        }

        // Emptying out the remaining characters in the stack
        s = "";
        while (st.Count > 0) {
            s = st.Pop() + s;
        }

        // Repeating the same process with the other type of pairs (if necessary)
        for (int i = s.Length - 1; i >= 0; i--) {
            if (st.Count > 0 && s[i] == b[0] && st.Peek() == b[1]) {
                st.Pop();
                answer += y;
            } else {
                st.Push(s[i]);
            }
        }

        return answer;
    }

    public static void Main() {
        string s = "abppprrr";
        int x = 5, y = 4;
        int answer = maxCost(x, y, s);
        Console.WriteLine(answer);
    }
}
JavaScript
function maxCost(x, y, s) {
    let answer = 0;

    // Setting up the priority of different pairs
    let a = 'pr';
    let b = 'rp';

    // Checking which pair has a higher priority
    if (x < y) {
        [x, y] = [y, x];
        [a, b] = [b, a];
    }

    const st = [];
    
    // Iterating through the input string from right to left
    for (let i = s.length - 1; i >= 0; i--) {
        // Checking if the current character and the top of the stack
        // form a valid pair and reducing the size of the stack and 
        // updating the answer accordingly
        if (st.length > 0 && s[i] === a[0] && st[st.length - 1] === a[1]) {
            st.pop();
            answer += x;
        } else {
            st.push(s[i]);
        }
    }

    // Convert stack back to string
    s = st.reverse().join('');

    // Repeating the same process with the other type of pairs (if necessary)
    for (let i = s.length - 1; i >= 0; i--) {
        if (st.length > 0 && s[i] === b[0] && st[st.length - 1] === b[1]) {
            st.pop();
            answer += y;
        } else {
            st.push(s[i]);
        }
    }

    return answer;
}

const s = 'abppprrr';
const x = 5, y = 4;
const answer = maxCost(x, y, s);
console.log(answer);  // Output the result

Output
15

Next Article

Similar Reads