We have a string made of lowercase letters, and we can repeatedly remove either "ab" or "ba" from it, scoring x or y points respectively each time. The goal is to maximize the total score.
Only the characters 'a' and 'b' matter. Any other character acts as a wall that separates independent groups of a's and b's, because a removal needs an 'a' adjacent to a 'b' and a wall character can never sit between two characters that get removed. Within each group, the question is how to pair up a's and b's to score the most.
Ordering decides the score. If removing "ab" pays more than "ba" (x > y), remove all "ab" pairs first, then remove whatever "ba" pairs remain from the leftovers. If y > x, do the opposite. Each 'a' and each 'b' can take part in at most one removal, so spending a character on the higher-scoring pair whenever possible never loses points compared to saving it for the lower-scoring pair.
1 <= s.length <= 10^5: a solution that repeatedly scans and rebuilds the string after each removal is O(n^2) and too slow at this length. We want a single-pass O(n) method.1 <= x, y <= 10^4: both values are positive, so every removal we can make adds points. There is never a reason to skip a removal. The maximum possible score is about (10^5 / 2) x 10^4 = 5 x 10^8, which fits in a 32-bit signed integer.s consists of lowercase English letters: characters other than 'a' and 'b' act as separators and cannot be part of any removal.Repeatedly scan the string for the higher-value pair and delete it. If x >= y, search for "ab", remove the first one found, add x to the score, and scan again. Once no "ab" remains, switch to "ba" and repeat. If y > x, do the reverse: clear out all "ba" pairs first, then "ab".
This is the by-hand method, and it is correct. The cost is that deleting a pair shifts the rest of the string and forces another scan, so the work grows quickly on long inputs.
Loading animation...
After each removal, only the characters that become newly adjacent at the deletion point can form a new pair. A stack captures exactly that adjacency: it keeps the running sequence of unremoved characters, with the most recently kept character on top. The next approach uses one to process each character a single time.
A stack processes the string in one pass. We push characters one at a time. Before pushing, we compare the current character against the character on top of the stack. If they form the pair being removed, we pop the top instead of pushing and add the points. This removes the pair without rebuilding the string, and it handles cascades correctly: after a pop, the new top is whatever sat behind the removed pair, which is exactly the character that becomes adjacent once the pair is gone.
One stack pass removes every copy of a single pair. To handle both pairs in priority order, run two passes. The first pass removes the higher-value pair across the whole string. Its leftovers feed a second pass that removes the lower-value pair. If x > y the higher-value pair is "ab"; if y > x it is "ba".
Within one segment of a's and b's, the number of removals is capped at min(countA, countB), since every removal consumes one 'a' and one 'b'. The greedy strategy reaches that cap while filling it with the most valuable pairs: it removes as many higher-value pairs as the layout permits, then spends the remaining characters on lower-value pairs. Removing the higher-value pair first never blocks a removal the other order would have allowed, because both orders consume one 'a' and one 'b' per pair and bottom out at the same min(countA, countB) total. No alternative ordering can score more. This is the standard exchange argument.
Loading animation...
The stack approach uses O(n) space, but the stack only tracks how many characters are waiting within the current segment. The next approach replaces it with two integer counters and drops the space to O(1).
The stack only ever holds 'a' and 'b' characters waiting inside the current segment, and a separator resets it to empty. That makes its contents simple enough to replace with two integers. While scanning a segment, track count1, the number of c1 characters (the high pair's first character) currently waiting. When c2 (the high pair's second character) arrives, it either consumes one waiting c1, forming a high-value pair, or, if none is waiting, accumulates in count2. A separator or the end of the string closes the segment, and the leftovers form min(count1, count2) low-value pairs.
Incrementing count1 mirrors pushing c1 onto the stack, and decrementing it when c2 arrives mirrors popping to form the high-value pair. Because both pair types within a segment consume one 'a' and one 'b', the high-value pass leaves exactly what a stack would leave: count1 unmatched c1's and count2 unmatched c2's, with no high-value pair possible between them, since every c2 that had a c1 before it already paired. Those leftovers form min(count1, count2) low-value pairs, the cap for the segment. Summing over segments matches the total from two stack passes.
Loading animation...