- Data Structure
- Networking
- RDBMS
- Operating System
- Java
- MS Excel
- iOS
- HTML
- CSS
- Android
- Python
- C Programming
- C++
- C#
- MongoDB
- MySQL
- Javascript
- PHP
- Physics
- Chemistry
- Biology
- Mathematics
- English
- Economics
- Psychology
- Social Studies
- Fashion Studies
- Legal Studies
- Selected Reading
- UPSC IAS Exams Notes
- Developer's Best Practices
- Questions and Answers
- Effective Resume Writing
- HR Interview Questions
- Computer Glossary
- Who is Who
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.