- 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
Lexicographically largest possible by merging two strings by adding one character at a time
Lexicographic means the algorithm by using which we can arrange given words in alphabetical order, the same concept which is used in dictionaries. The largest possible string that we would get by merging two strings taking one-character element at a time so that the order is lexicographic can be obtained by arranging alphabets in decreasing order or descending order keeping the sequence of elements in mind.
Problem Statement
Now, in this problem, we need to find lexicographically the largest possible string we get by merging two given strings. To understand this problem, we should know the basic concept we use for arranging strings in lexicographic order.
Let’s try to understand this problem with the help of some examples.
Input
string1 = "cabaa", string2 = "bcaaa"
Output
"cbcabaaaaa"
Explanation
One way to get the lexicographically largest merged string is −
Take from string1 “c” and append this in an initial empty string, this leaves us with string1 “abaa” and string2 “bcaaa”
Now, take from string2 “b” making the merged string “cb” and leaving string1 as “abaa” and string2 as “caaa”
Again take from string2 “c” making the merged string “cbc” and leaving string1 as “abaa” and string2 as “aaa”
Take from string1 “a” making the merged string “cbca” and leaving string1 as “baa” and string2 as “aaa”
Again take from string1 “b” making the merged string “cbcab” and leaving string1 as “aa” and string2 as “aaa”
Now, append all remaining a’s from string1 and string2 to the merged string to get the end result.
Input
string1 = "baa", string2 = "bcaac"
Output
"bcbaacaa"
Explanation
Here, to get the lexicographically largest merged string we will take an element from string2 ”b” and then again from string2 making it “bc”. Now, we will take “b” from string1 making the merged string “bcb” rest we will pick “aac” from string2 and “aa” from string1 making the merged string “bcbaacaa” as the expected output.
Problem Explanation
Let’s try to understand the problem and find its solution. We can solve this problem by two approaches: one by using recursion and the other by using iteration in which we would use the concept of greedy pointers. Greedy pointers are the use of pointers when we would make an optimal choice at a small step to get an overall optimal solution as a whole.
Approach 1 - Brute force recursive solution
Here, we will use the concept of the recursive function where the base condition is defined when the size of either of the two strings becomes zero. Then we will compare the first character of the remaining strings whichever is greater will be returned in combination with a call to the function where its substring is called.
Example
Now, let us implement the above approach in different programming languages: C, C++, Java, and Python −
#include<bits/stdc++.h> using namespace std; // Make a function to get the Lexicographically largest possible string string helper(string word1, string word2) { // base condition for recursion if (word1.empty() || word2.empty()){ return word1 + word2; } // Check the character from which string would be chosen first among both strings if (word1 > word2) { return word1[0] + helper(word1.substr(1), word2); } // return the final answer which would provide optimal result return word2[0] + helper(word1, word2.substr(1)); } int main() { // Give two strings by the user string string1 = "cabaa"; string string2 = "bcaaa"; // Call the helper function cout << "The lexicographically largest possible string is: " << helper(string1, string2); return 0; }
Output
The lexicographically largest possible string is: cbcabaaaaa
public class Main { // Function to get the lexicographically largest possible string public static String helper(String word1, String word2) { // Base condition for recursion if (word1.isEmpty() || word2.isEmpty()) { return word1 + word2; } // Check the character from which string would be chosen first among both strings if (word1.compareTo(word2) > 0) { return word1.charAt(0) + helper(word1.substring(1), word2); } // Return the final answer which would provide the optimal result return word2.charAt(0) + helper(word1, word2.substring(1)); } public static void main(String[] args) { // Provide two strings String string1 = "cabaa"; String string2 = "bcaaa"; // Call the helper function String result = helper(string1, string2); // Print the lexicographically largest possible string System.out.println("The lexicographically largest possible string is: " + result); } }
Output
The lexicographically largest possible string is: cbcabaaaaa
# Function to get the lexicographically largest possible string def helper(word1, word2): # Base condition for recursion if not word1 or not word2: return word1 + word2 # Check the character from which string would be chosen first among both strings if word1 > word2: return word1[0] + helper(word1[1:], word2) # Return the final answer which would provide the optimal result return word2[0] + helper(word1, word2[1:]) # Main function def main(): # Provide two strings string1 = "cabaa" string2 = "bcaaa" # Call the helper function result = helper(string1, string2) # Print the lexicographically largest possible string print("The lexicographically largest possible string is:", result) if __name__ == "__main__": main()
Output
The lexicographically largest possible string is: cbcabaaaaa
Complexities for the Above Code
Time complexity − O(m*n); where ‘m’ and ‘n’ are the size of given two strings as the initial input provided by the user. Here is an inbuilt recursion stack that would be used to run through all the given elements present in both strings.
Space complexity − O(1); though an inbuilt recursion stack would be used here but still it would not take up space as it is used as a runtime memory.
Approach 2 - Optimal Solution Using Greedy Pointer Technique
Algorithm
Run a loop until we reach either the size of the first string(for a variable ‘i’) or else the size of the second string(for a variable ‘j’).
Check which character comes later according to ASCII codes and we will append that character to the merged string.
After we reach the stopping condition of the loop we will check which among ‘i’ or ‘j’ reached its limit.
We will run a separate loop to make the other one reach its stopping point so that we can take the characters of both strings in the merged string.
Example
Now, let us implement the above approach in different programming languages: C, C++, Java, and Python −
#include <stdio.h> #include <string.h> #include <stdlib.h> // Function to get the lexicographically largest possible string char* helper(const char* word1, const char* word2) { int n = strlen(word1); int m = strlen(word2); char* ans = (char*)malloc(n + m + 1); // Allocate memory for the result string int i = 0, j = 0, k = 0; while (i < n && j < m) { // Check which character is maximum if (strcmp(&word1[i], &word2[j]) > 0) { ans[k++] = word1[i++]; } else { ans[k++] = word2[j++]; } } // If the condition for 'i' was not satisfied, append the rest of the first string to the final answer while (i < n) { ans[k++] = word1[i++]; } // If the condition for 'j' was not satisfied, append the rest of the second string to the final answer while (j < m) { ans[k++] = word2[j++]; } ans[k] = '\0'; // Null-terminate the result string return ans; } int main() { // Given two strings by the user const char* string1 = "cabaa"; const char* string2 = "bcaaa"; // Call the helper function char* result = helper(string1, string2); // Print the lexicographically largest possible string printf("The lexicographically largest possible string is: %s\n", result); // Free the allocated memory free(result); return 0; }
Output
The lexicographically largest possible string is: cbcabaaaaa
#include<bits/stdc++.h> using namespace std; // Make a function to get the Lexicographically largest possible string string helper(string word1, string word2) { // Define size of string1 and string2 int i = 0, j = 0, n = word1.size(), m = word2.size(); string ans; // Using the pointer technique while(i < n && j < m) { // Check which character is maximum if(word1.substr(i) > word2.substr(j)){ ans += word1[i]; i++; } else { ans += word2[j]; j++; } } // If the condition for 'i' was not satisfied append the rest first string to the final answer while(i < n){ ans += word1[i]; i++; } // If the condition for 'i' was not satisfied append the rest first string to the final answer while(j < m){ ans += word2[j]; j++; } // return the final answer which would provide the optimal result return ans; } int main() { // Given two strings by the user string string1 = "cabaa"; string string2 = "bcaaa"; // Call the helper function cout << "The lexicographically largest possible string is: " << helper(string1, string2); return 0; }
Output
The lexicographically largest possible string is: cbcabaaaaa
public class Main { // Make a function to get the lexicographically largest possible string public static String helper(String word1, String word2) { int i = 0, j = 0; int n = word1.length(); int m = word2.length(); StringBuilder ans = new StringBuilder(); // Use StringBuilder to efficiently build the string // Using a pointer technique while (i < n && j < m) { // Check which character is maximum if (word1.substring(i).compareTo(word2.substring(j)) > 0) { ans.append(word1.charAt(i)); i++; } else { ans.append(word2.charAt(j)); j++; } } // If the condition for 'i' was not satisfied, append the rest of the first string to the final answer while (i < n) { ans.append(word1.charAt(i)); i++; } // If the condition for 'j' was not satisfied, append the rest of the second string to the final answer while (j < m) { ans.append(word2.charAt(j)); j++; } // Return the final answer which provides the optimal result return ans.toString(); } public static void main(String[] args) { // Given two strings by the user String string1 = "cabaa"; String string2 = "bcaaa"; // Call the helper function System.out.println("The lexicographically largest possible string is: " + helper(string1, string2)); } }
Output
The lexicographically largest possible string is: cbcabaaaaa
# Function to get the lexicographically largest possible string def helper(word1, word2): i, j = 0, 0 n, m = len(word1), len(word2) ans = [] # Using a pointer technique while i < n and j < m: # Check which character is maximum if word1[i:] > word2[j:]: ans.append(word1[i]) i += 1 else: ans.append(word2[j]) j += 1 # If the condition for 'i' was not satisfied, append the rest of the first string to the final answer while i < n: ans.append(word1[i]) i += 1 # If the condition for 'j' was not satisfied, append the rest of the second string to the final answer while j < m: ans.append(word2[j]) j += 1 # Join the characters to form the final answer return ''.join(ans) # Main function def main(): # Given two strings by the user string1 = "cabaa" string2 = "bcaaa" # Call the helper function result = helper(string1, string2) print("The lexicographically largest possible string is:", result) if __name__ == "__main__": main()
Output
The lexicographically largest possible string is: cbcabaaaaa
Complexities for the Above Code
Time complexity − O(m+n); where ‘m’ and ‘n’ are the size of given two strings as the initial input provided by the user. Here a loop would be used (n + m) times to get the final solution.
Space complexity − O(n+m); here a string ‘ans’ is used to store our output which would take up (n+m) size in the memory.
Conclusion
In this article, to find the lexicographically largest possible string by merging two strings, provided to us by the user, by adding one character at a time. Firstly, we will apply the naive approach to get the output with the help of the recursive process. We will ponder upon all the available options of the merged string and recursion would provide us with the most apt output required to satisfy the lexicographic condition keeping the order of two strings in mind. But this approach will take more time to execute the code. So, we will go with another approach, which is iterative, using greedy pointers to enhance time complexity, and through this procedure, we will be able to reach the final output in one iteration go only.