Find And Replace in String

MEDIUM

Description

You are given a 0-indexed string s that you must perform k replacement operations on. The replacement operations are given as three 0-indexed parallel arrays, indices, sources, and targets, all of length k.

To complete the ith replacement operation:

  1. Check if the substring sources[i] occurs at index indices[i] in the original string s.
  2. If it does not occur, do nothing.
  3. Otherwise if it does occur, replace that substring with targets[i].

For example, if s = "abcd", indices[i] = 0, sources[i] = "ab", and targets[i] = "eee", then the result of this replacement will be "eeecd".

All replacement operations must occur simultaneously, meaning the replacement operations should not affect the indexing of each other. The testcases will be generated such that the replacements will not overlap.

  • For example, a testcase with s = "abc", indices = [0, 1], and sources = ["ab","bc"] will not be generated because the "ab" and "bc" replacements overlap.

Return the resulting string after performing all replacement operations on s.

A substring is a contiguous sequence of characters in a string.

 

Example 1:

Input: s = "abcd", indices = [0, 2], sources = ["a", "cd"], targets = ["eee", "ffff"]
Output: "eeebffff"
Explanation:
"a" occurs at index 0 in s, so we replace it with "eee".
"cd" occurs at index 2 in s, so we replace it with "ffff".

Example 2:

Input: s = "abcd", indices = [0, 2], sources = ["ab","ec"], targets = ["eee","ffff"]
Output: "eeecd"
Explanation:
"ab" occurs at index 0 in s, so we replace it with "eee".
"ec" does not occur at index 2 in s, so we do nothing.

 

Constraints:

  • 1 <= s.length <= 1000
  • k == indices.length == sources.length == targets.length
  • 1 <= k <= 100
  • 0 <= indexes[i] < s.length
  • 1 <= sources[i].length, targets[i].length <= 50
  • s consists of only lowercase English letters.
  • sources[i] and targets[i] consist of only lowercase English letters.

Approaches

Checkout 3 different approaches to solve Find And Replace in String. Click on different approaches to view the approach and algorithm in detail.

Brute Force: Scan String and Check Operations

This is a straightforward brute-force approach. We iterate through the input string s with a pointer. At each position, we loop through all k available operations to see if one applies. If a matching operation is found, we perform the replacement and advance our pointer accordingly. Otherwise, we copy the character and advance the pointer by one.

Algorithm

  • Initialize a StringBuilder to build the result string.
  • Initialize a pointer i = 0 to traverse the input string s.
  • Loop while i is less than the length of s.
  • Inside the loop, search for a matching operation at index i. Initialize a flag matchFound = false.
  • Iterate from j = 0 to k-1:
    • If indices[j] == i and s.startsWith(sources[j], i):
      • Append targets[j] to the StringBuilder.
      • Advance i by sources[j].length().
      • Set matchFound = true and break the inner loop (since replacements are non-overlapping).
  • If matchFound is false after checking all operations, it means no replacement starts at i.
    • Append s.charAt(i) to the StringBuilder.
    • Increment i by 1.
  • After the main loop finishes, convert the StringBuilder to a string and return it.
class Solution {
    public String findReplaceString(String s, int[] indices, String[] sources, String[] targets) {
        StringBuilder result = new StringBuilder();
        int k = indices.length;
        int i = 0;
        while (i < s.length()) {
            boolean replaced = false;
            for (int j = 0; j < k; j++) {
                // Check if an operation starts at the current index i and the source matches
                if (indices[j] == i && s.startsWith(sources[j], i)) {
                    result.append(targets[j]);
                    i += sources[j].length();
                    replaced = true;
                    break; // Non-overlapping, so we can break after finding one match
                }
            }
            if (!replaced) {
                result.append(s.charAt(i));
                i++;
            }
        }
        return result.toString();
    }
}

Complexity Analysis

Time Complexity: O(N * K * L_s), where `N` is the length of `s`, `K` is the number of operations, and `L_s` is the maximum length of a source string. The outer loop runs up to `N` times. In each iteration, we may loop through all `K` operations, and for each, `startsWith` takes `O(L_s)` time.Space Complexity: O(L_res), where `L_res` is the length of the resulting string. This space is primarily used by the `StringBuilder` to construct the output.

Pros and Cons

Pros:
  • Simple logic, easy to understand and implement.
  • Minimal auxiliary space besides the result builder.
Cons:
  • Inefficient due to the nested loop structure, leading to a high time complexity, especially for large N and K.

Code Solutions

Checking out 3 solutions in different languages for Find And Replace in String. Click on different languages to view the code.

class Solution {
public
  String findReplaceString(String s, int[] indices, String[] sources,
                           String[] targets) {
    int n = s.length();
    var d = new int[n];
    Arrays.fill(d, -1);
    for (int k = 0; k < indices.length; ++k) {
      int i = indices[k];
      if (s.startsWith(sources[k], i)) {
        d[i] = k;
      }
    }
    var ans = new StringBuilder();
    for (int i = 0; i < n;) {
      if (d[i] >= 0) {
        ans.append(targets[d[i]]);
        i += sources[d[i]].length();
      } else {
        ans.append(s.charAt(i++));
      }
    }
    return ans.toString();
  }
}

Video Solution

Watch the video walkthrough for Find And Replace in String



Algorithms:

Sorting

Data Structures:

ArrayHash TableString

Subscribe to Scale Engineer newsletter

Learn about System Design, Software Engineering, and interview experiences every week.

No spam, unsubscribe at any time.