1910. Remove All Occurrences of a Substring
SourceBiweekly Contest 55 Q2DifficultyMediumRating1460
Description
Given two strings s and part, perform the following operation on s until all occurrences of the substring part are removed:
- Find the leftmost occurrence of the substring
partand remove it froms.
Return s after removing all occurrences of part.
A substring is a contiguous sequence of characters in a string.
Example 1:
Input: s = "daabcbaabcbc", part = "abc" Output: "dab" Explanation: The following operations are done: - s = "daabcbaabcbc", remove "abc" starting at index 2, so s = "dabaabcbc". - s = "dabaabcbc", remove "abc" starting at index 4, so s = "dababc". - s = "dababc", remove "abc" starting at index 3, so s = "dab". Now s has no occurrences of "abc".
Example 2:
Input: s = "axxxxyyyyb", part = "xy" Output: "ab" Explanation: The following operations are done: - s = "axxxxyyyyb", remove "xy" starting at index 4 so s = "axxxyyyb". - s = "axxxyyyb", remove "xy" starting at index 3 so s = "axxyyb". - s = "axxyyb", remove "xy" starting at index 2 so s = "axyb". - s = "axyb", remove "xy" starting at index 1 so s = "ab". Now s has no occurrences of "xy".
Constraints:
1 <= s.length <= 10001 <= part.length <= 1000s andpartconsists of lowercase English letters.
Solutions
Solution 1: Brute Force
Thinking
Both \(s\) and \(\textit{part}\) are at most \(10^3\) long, so repeatedly locating and erasing one occurrence is acceptable.
Each step replaces the leftmost \(\textit{part}\). A later concatenation may recreate \(\textit{part}\), so the loop continues until none remain.
Every replacement shortens \(s\), so the process terminates and matches the required leftmost-first order.
1 2 3 4 5 | |
1 2 3 4 5 6 7 8 | |
1 2 3 4 5 6 7 8 9 10 | |
1 2 3 4 5 6 | |
1 2 3 4 5 6 | |
Solution 2: Stack
Thinking
Solution 1 rescans the whole string after every deletion. Each deletion shortens \(s\) by at least one character, so there can be \(O(n)\) rounds and the total time is \(O(n^2)\).
While reading left to right, any remaining occurrence of \(\textit{part}\) that is leftmost must end at the character just read. An earlier match would already have been removed.
Keep the surviving characters on a stack. After each push, pop the last \(m\) characters when they equal \(\textit{part}\). One pass performs every leftmost deletion.
Scan \(s\) from left to right and store the characters that have not been removed in a string \(st\). Append the current character. If \(st\) has length at least \(m = |\textit{part}|\) and its last \(m\) characters are \(\textit{part}\), delete those \(m\) characters. After the scan, \(st\) is the answer.
This matches Solution 1. At every moment \(st\) contains no occurrence of \(\textit{part}\), so the next match must end at the character just appended, which is the leftmost occurrence in what remains.
The time complexity is \(O(nm)\), and the space complexity is \(O(n)\), where \(n\) and \(m\) are the lengths of \(s\) and \(\textit{part}\).
1 2 3 4 5 6 7 8 9 | |
1 2 3 4 5 6 7 8 9 10 11 12 13 | |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 | |
1 2 3 4 5 6 7 8 9 10 11 | |
1 2 3 4 5 6 7 8 9 10 11 | |