Welcome to Subscribe On Youtube

1910. Remove All Occurrences of a Substring

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 part and remove it from s.

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 <= 1000
  • 1 <= part.length <= 1000
  • s​​​​​​ and part consists of lowercase English letters.

Solutions

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(n \times m)$ and the space complexity is $O(n)$, where $n$ and $m$ are the lengths of $s$ and $\textit{part}$.

  • class Solution {
        public String removeOccurrences(String s, String part) {
            while (s.contains(part)) {
                s = s.replaceFirst(part, "");
            }
            return s;
        }
    }
    
    
    // Solution 2
    class Solution {
        public String removeOccurrences(String s, String part) {
            int m = part.length();
            StringBuilder st = new StringBuilder();
            for (int i = 0; i < s.length(); ++i) {
                st.append(s.charAt(i));
                if (st.length() >= m && st.substring(st.length() - m).equals(part)) {
                    st.setLength(st.length() - m);
                }
            }
            return st.toString();
        }
    }
    
    
  • class Solution {
    public:
        string removeOccurrences(string s, string part) {
            int m = part.size();
            while (s.find(part) != -1) {
                s = s.erase(s.find(part), m);
            }
            return s;
        }
    };
    
    
    // Solution 2
    class Solution {
    public:
        string removeOccurrences(string s, string part) {
            int m = part.size();
            string st;
            for (char c : s) {
                st.push_back(c);
                if ((int) st.size() >= m && st.compare(st.size() - m, m, part) == 0) {
                    st.erase(st.size() - m);
                }
            }
            return st;
        }
    };
    
    
  • class Solution:
        def removeOccurrences(self, s: str, part: str) -> str:
            while part in s:
                s = s.replace(part, '', 1)
            return s
    
    
    
    # Solution 2
    class Solution:
        def removeOccurrences(self, s: str, part: str) -> str:
            m = len(part)
            st = []
            for c in s:
                st.append(c)
                if len(st) >= m and ''.join(st[-m:]) == part:
                    del st[-m:]
            return ''.join(st)
    
    
  • func removeOccurrences(s string, part string) string {
    	for strings.Contains(s, part) {
    		s = strings.Replace(s, part, "", 1)
    	}
    	return s
    }
    
    
    // Solution 2
    func removeOccurrences(s string, part string) string {
    	m := len(part)
    	st := make([]byte, 0, len(s))
    	for i := 0; i < len(s); i++ {
    		st = append(st, s[i])
    		if len(st) >= m && string(st[len(st)-m:]) == part {
    			st = st[:len(st)-m]
    		}
    	}
    	return string(st)
    }
    
    
  • function removeOccurrences(s: string, part: string): string {
        while (s.includes(part)) {
            s = s.replace(part, '');
        }
        return s;
    }
    
    
    
    // Solution 2
    function removeOccurrences(s: string, part: string): string {
        const m = part.length;
        const st: string[] = [];
        for (const c of s) {
            st.push(c);
            if (st.length >= m && st.slice(-m).join('') === part) {
                st.length -= m;
            }
        }
        return st.join('');
    }
    
    

All Problems

All Solutions