Replace two Substrings (of a String) with Each Other


You are given three strings S, A and B. You have to replace every sub−string of S equal to A with B and every sub−string of S equal to B with A. There is a possibility that two or more sub−strings matching A or B overlap. To avoid this confusion about the situation, you have to find the leftmost sub−string that matches A or B, replace it, and then continue with the rest of the string.

Input

S = “aab”, A = “aa”, B = “bb” 

Output

“bbb” 

Match the first two characters with A and replace it with B we get ‘bbb’. Then continue the algorithm starting at index 3 and we don’t find any more matches.

Input

S = “aabbaabb”, A = “aa”, B = “bb” 

Output

“bbaabbaa” 

Replace all the occurrences of “aa” with “bb” and “bb” with “aa”, so the final string is “bbaabbaa”.

Solution

The goal is to discover the leftmost substring in the string S that matches either A or B. When both A and B are located at the same index, the sub−string that matches A is changed first. The non−matching sub−string is then added to the outcome, and the process is repeated until no further matches are found. If no additional matches are discovered, the final sub−string is added to the final result.

The time complexity of this algorithm is O(N*M), where N is the length of the string S and M is the length of the strings A and B. In the worst scenario, we might have to look through the full string S in order to find every match. Since we must at least once analyze each character in the string, this is also an ideal time complexity.

Java Implementation

Let us see the Java implementation

Example

public class ReplaceSubstring {
	 //method to replace string
    public static String replaceSubstring(String S, String A, String B) {
        StringBuilder sb = new StringBuilder();
        int i = 0;
        while (i < S.length()) {
            // Find the leftmost sub-string that matches A or B
            int aIndex = S.indexOf(A, i);
            int bIndex = S.indexOf(B, i);
            if (aIndex == -1 && bIndex == -1) {
                // No more matches found
                sb.append(S.substring(i));
                break;
            } else if (aIndex == -1 || (bIndex != -1 && bIndex < aIndex)) {
                // Replace the sub-string matching B
                sb.append(S.substring(i, bIndex)).append(A);
                i = bIndex + B.length();
            } else {
                // Replace the sub-string matching A
                sb.append(S.substring(i, aIndex)).append(B);
                i = aIndex + A.length();
            }
        }
        return sb.toString();
    }
	 //Driver method
    public static void main(String[] args) {
        String S = "aabbcc";
        String A = "aa";
        String B = "bb";
        String result = replaceSubstring(S, A, B);
        System.out.println(result);
    }
}

Output

bbaacc

Alternative Approach

The approach we presented earlier has a time complexity of O(N*M), where N is the length of the string S and M is the length of the strings A and B. This is already an optimal time complexity since we need to examine each character of the string at least once.

However, we can optimize the implementation by using a StringBuilder to construct the result string instead of repeatedly concatenating substrings. We can also avoid using indexOf() to search for the next match by manually iterating through the string and comparing substrings. Here's an updated implementation with these optimizations:

Example

public class ReplaceSubstring {
	//method to replace string
    public static String replaceSubstring(String S, String A, String B) {
        StringBuilder sb = new StringBuilder(S.length());
        int i = 0;
        while (i < S.length()) {
            // Check if the current substring matches A
            if (i + A.length() <= S.length() && S.substring(i, i + A.length()).equals(A)) {
                sb.append(B);
                i += A.length();
            }
            // Check if the current substring matches B
            else if (i + B.length() <= S.length() && S.substring(i, i + B.length()).equals(B)) {
                sb.append(A);
                i += B.length();
            }
            // Current substring does not match A or B
            else {
                sb.append(S.charAt(i));
                i++;
            }
        }
        return sb.toString();
    }
	
	//Driver method
    public static void main(String[] args) {
        String S = "aabbcc";
        String A = "aa";
        String B = "bb";
        String result = replaceSubstring(S, A, B);
        System.out.println(result);
    }
}

Output

bbaacc

This implementation has the same time complexity as the previous one, but it can be faster in practice due to the reduced overhead of string concatenation and indexOf calls.

Updated on: 22-Aug-2023

77 Views

Kickstart Your Career

Get certified by completing the course

Get Started
Advertisements