Skip to content

Commit b8a3a07

Browse files
Merge branch 'main' of https://github.com/contextlab/leetcode-solutions into main
2 parents cb97498 + fd9aeca commit b8a3a07

File tree

1 file changed

+93
-0
lines changed

1 file changed

+93
-0
lines changed

Diff for: problems/1717/jeremymanning.md

+93
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,93 @@
1+
# [Problem 1717: Maximum Score From Removing Substrings](https://leetcode.com/problems/maximum-score-from-removing-substrings/description/?envType=daily-question)
2+
3+
## Initial thoughts (stream-of-consciousness)
4+
- I think all of the examples could be solved using something like:
5+
- prioritize `'ab'` if `x > y` and `'ba'` otherwise
6+
- remove the higher-priority pattern (tracking points) until there are none left
7+
- then remove the lower-priority pattern (tracking points) until there are none left
8+
- For trickier inputs, it's possible that new instances of the higher-priority pattern could emerge only after removing the lower-priority patterns. In fact, maybe this could happen even after just a single lower-priority pattern removal. So maybe we need to do something like:
9+
- loop until nothing else can be done:
10+
- remove higher priority patterns until there are none left
11+
- remove a single lower priority pattern
12+
- if none found, return the current score
13+
- return the current score
14+
- This is very inefficient: finding substrings requires looping through all of `s` in $O(n)$ time, where $n$ is the length of `s`, every time we search for another instance. In the worst case (e.g., something like `abababababab...ababab` it'll take $O(n^2)$ time, which may be too long given that `s` can be up to $10^5$ characters long
15+
- One potential way to optimize would be to break the string into segments bounded by non-a/b characters. Then we could compute the max score for each of these parts and sum them together.
16+
- Another thing we can do to optimize would be to replace every consecutive sequence of non-a/b characters with a single non-a/b character (e.g., "x"). That might substantially shorten the total length of the string.
17+
- A hypothetical edge case that I'm not sure can happen (but if so, we'll need to take it into account) is if there were some case where we could get *two* matches of the lower-priority string by sacrificing *one* instance of the higher-priority string. Actually: a simple case might be: `s = 'abab'`, where `x < y`. But if `x > y/2` then our best move *isn't* to remove the middle "ba" sequence-- it's to remove each "ab" sequence in turn to cash in two instances of the lower point value to get a higher total. So those solutions above won't quite work; we need to take this into account. I wonder if we might even encounter an example where sacrificing one higher priority string could lead to *three* (or more) matches of lower-priority strings.
18+
- Let's try to think through some potential cases of what can happen with a given sequence of a/b characters:
19+
- If the length is less than or equal to two, there's nothing to search (either we have a match of one of the patterns, or not)
20+
- If the length is equal to three, we can only remove at most one substring (so if both are available we just return `max(x, y)` and otherwise we return the value for whichever string is found in the sequence, if any, or 0 otherwise).
21+
- If the length is equal to four, let's see what the possibilities are:
22+
- aaaa
23+
- aaab
24+
- aaba
25+
- aabb
26+
- abaa
27+
- abab
28+
- abba
29+
- abbb
30+
- baaa
31+
- baab
32+
- baba
33+
- babb
34+
- bbaa
35+
- bbab
36+
- bbba
37+
- bbbb
38+
- Aside: this is like counting in binary...maybe there's some shortcut we could take based on that?
39+
- after taking a pause....
40+
- Ok, in re-thinking the "abab" example above, it's not correct as I described it. If we remove "ba" first, then we're still left with an instance of "ab" which we can use to get those points. So actually, prioritizing the higher-scoring substring *does* seem to make sense. The real issue is with efficiency.
41+
- another pause...
42+
- let's try a "stack" implementation to avoid having to loop through the same string a gajillion times:
43+
- to detect (with priority) the two-character substring `sub` with point value `p`:
44+
- loop through each character, `c` of `s`:
45+
- if the stack is not empty, and if the top of the stack + `c` matches `sub`:
46+
- increment total points by `p`
47+
- pop the top of the stack ("removes" the substring)
48+
- otherwise push `c` to the stack
49+
- return the total points, along with `''.join(stack)` (i.e., the updated string, with matches removed)
50+
- run this first for the higher-priority substring, and then for the lower-priority substring, and then return the sum of the resulting point totals
51+
52+
## Refining the problem, round 2 thoughts
53+
- thinking through edge cases:
54+
- can we have an empty input string? no, we're given that `1 <= s.length <= 10^5`
55+
- can the "points values" (`x` or `y`) ever be negative? no, we're given that `1 <= x, y <= 10^4`
56+
- let's try this!
57+
58+
## Attempted solution(s)
59+
```python
60+
class Solution:
61+
def maximumGain(self, s: str, x: int, y: int) -> int:
62+
def helper(s, pattern, p):
63+
stack = []
64+
points = 0
65+
for c in s:
66+
if len(stack) > 0 and stack[-1] + c == pattern:
67+
stack.pop()
68+
points += p
69+
else:
70+
stack.append(c)
71+
return ''.join(stack), points
72+
73+
if x > y:
74+
high, low, p1, p2 = 'ab', 'ba', x, y
75+
else:
76+
high, low, p1, p2 = 'ba', 'ab', y, x
77+
78+
first_pass, total1 = helper(s, high, p1)
79+
_, total2 = helper(first_pass, low, p2)
80+
81+
return total1 + total2
82+
```
83+
- given test cases: pass
84+
- other tests:
85+
- 's = "ababababab"`, `x = 5`, `y = `10`: pass
86+
- 's = "ababababab"`, `x = 10`, `y = `5`: pass
87+
- `s = "abacbabcabacbabc"`, `x = 1`, `y = 1`: pass
88+
- ok, looks reasonable...submitting...
89+
90+
![Screenshot 2024-07-12 at 9 05 26 AM](https://github.com/user-attachments/assets/0010d7ff-d2e1-46ac-9c8f-43a428c6405c)
91+
92+
done!
93+

0 commit comments

Comments
 (0)