Find lexicographical smallest string by performing the given operations N times
Given a string S of N characters, the task is to find the smallest lexicographical string after performing each of the following operations N times in any order:
- Remove the 1st character of S and insert it into a stack X.
- Remove the top of stack X and append it to the end of another string Y which is initially empty.
Example:
Input: S = “cab”
Output: abc
Explanation: The given string can be obtained using the following operations:
- Perform operation 1. Hence, S = “ab”, X = “c”, Y = “”.
- Perform operation 1. Hence, S = “b”, X = “ca”, Y = “”.
- Perform operation 2. Hence, S = “b”, X = “c”, Y = “a”.
- Perform operation 1. Hence, S = “”, X = “cb”, Y = “a”.
- Perform operation 2. Hence, S = “”, X = “c”, Y = “ab”.
- Perform operation 2. Hence, S = “”, X = “”, Y = “abc”.
Now, each of the given operations is performed N times and the string obtained is “abc” which is the smallest possible.
Input: S = “acdb”
Output: abdc
Approach: The given problem can be solved using a greedy approach. The idea is to perform the 1st operation till the top of the stack contains the smallest character after which it can be appended to the string Y. This can be efficiently done by maintaining a suffix array, where suff[i] stores the smallest ASCII value of the suffix till ith character. Below are the steps to follow:
- Traverse the string and create a suffix array suff[] as required.
- If stack X is not empty and suff[i] is greater than equal to top character of stack X, pop the top character of stack X and append it into string Y.
- Else If suff[i] is equal to the S[i] append into string Y.
- Else push character S[i] into the stack X.
Below is the implementation of the above approach:
C++
// C++ program of the above approach #include <bits/stdc++.h> using namespace std; // Function to find lexicographical smallest // string by performing the given operations string smallestString(string S) { // Stores the size of S int N = S.size(); // Suffix Array int suff[N + 1]; // Initial Condition suff[N] = INT_MAX; // Loop to calculate suffix array for ( int i = N - 1; i >= 0; i--) { suff[i] = min(suff[i + 1], ( int )S[i]); } // Initialize the stack X // and string y as empty stack< char > X; string Y = "" ; // Loop to traverse string for ( int i = 0; i < N; i++) { // If X is not empty and suff[i] // is greater than equal to top // character of stack X if (X.size() > 0 && suff[i] >= X.top()) { Y += X.top(); X.pop(); i--; } // If suff[i] is equal to S[i] else if (suff[i] == S[i]) { Y += S[i]; } // Otherwise push character // S[i] into the stack X else { X.push(S[i]); } } // Append all remaining characters // of X into string Y while (X.size() > 0) { Y += X.top(); X.pop(); } // Return Answer return Y; } // Driver Code int main() { string s = "acdb" ; cout << smallestString(s); return 0; } |
Java
// Java program of the above approach import java.util.*; class GFG { // Function to find lexicographical smallest // string by performing the given operations public static String smallestString(String S) { // Stores the size of S int N = S.length(); // Suffix Array int [] suff = new int [N + 1 ]; // Initial Condition suff[N] = Integer.MAX_VALUE; // Loop to calculate suffix array for ( int i = N - 1 ; i >= 0 ; i--) { suff[i] = Math.min(suff[i + 1 ], ( int )S.charAt(i)); } // Initialize the stack X // and string y as empty Stack<Character> X = new Stack<Character>(); String Y = "" ; // Loop to traverse string for ( int i = 0 ; i < N; i++) { // If X is not empty and suff[i] // is greater than equal to top // character of stack X if (X.size() > 0 && suff[i] >= X.peek()) { Y += X.peek(); X.pop(); i--; } // If suff[i] is equal to S[i] else if (suff[i] == S.charAt(i)) { Y += S.charAt(i); } // Otherwise push character // S[i] into the stack X else { X.push(S.charAt(i)); } } // Append all remaining characters // of X into string Y while (X.size() > 0 ) { Y += X.peek(); X.pop(); } // Return Answer return Y; } // Driver Code public static void main(String[] args) { String s = "acdb" ; System.out.print(smallestString(s)); } } // This code is contributed by Taranpreet |
Python3
# Python program of the above approach import sys # Function to find lexicographical smallest # string by performing the given operations def smallestString(S): # Stores the size of S N = len (S) # Suffix Array suff = [ 0 ] * (N + 1 ) # Initial Condition suff[N] = sys.maxsize # Loop to calculate suffix array for i in range (N - 1 , - 2 , - 1 ): suff[i] = min (suff[i + 1 ], ord (S[i])) # Initialize the stack X # and string y as empty X = [] Y = "" # Loop to traverse string for i in range ( 0 , N): # If X is not empty and suff[i] # is greater than equal to top # character of stack X if ( len (X) > 0 and suff[i] > = ord (X[ - 1 ])): Y = Y + X[ - 1 ] X.pop() i = i - 1 # If suff[i] is equal to S[i] elif (suff[i] = = ord (S[i])): Y = Y + S[i] # Otherwise push character # S[i] into the stack X else : X.append(S[i]) # Append all remaining characters # of X into string Y while ( len (X) > 0 ): Y = Y + X[ - 1 ] X.pop() # Return Answer return Y # Driver Code s = "acdb" print (smallestString(s)) # This code is contributed by Taranpreet |
C#
// C# program of the above approach using System; using System.Collections.Generic; class GFG { // Function to find lexicographical smallest // string by performing the given operations public static String smallestString(String S) { // Stores the size of S int N = S.Length; // Suffix Array int [] suff = new int [N + 1]; // Initial Condition suff[N] = int .MaxValue; // Loop to calculate suffix array for ( int i = N - 1; i >= 0; i--) { suff[i] = Math.Min(suff[i + 1], ( int )S[i]); } // Initialize the stack X // and string y as empty Stack< char > X = new Stack< char >(); String Y = "" ; // Loop to traverse string for ( int i = 0; i < N; i++) { // If X is not empty and suff[i] // is greater than equal to top // character of stack X if (X.Count > 0 && suff[i] >= X.Peek()) { Y += X.Peek(); X.Pop(); i--; } // If suff[i] is equal to S[i] else if (suff[i] == S[i]) { Y += S[i]; } // Otherwise push character // S[i] into the stack X else { X.Push(S[i]); } } // Append all remaining characters // of X into string Y while (X.Count > 0) { Y += X.Peek(); X.Pop(); } // Return Answer return Y; } // Driver Code public static void Main() { String s = "acdb" ; Console.Write(smallestString(s)); } } // This code is contributed by Saurabh Jaiswal |
Javascript
<script> // JavaScript code for the above approach // Function to find lexicographical smallest // string by performing the given operations function smallestString(S) { // Stores the size of S let N = S.length; // Suffix Array let suff = new Array(N + 1); // Initial Condition suff[N] = Number.MAX_VALUE; // Loop to calculate suffix array for (let i = N - 1; i >= 0; i--) { suff[i] = Math.min(suff[i + 1], S[i].charCodeAt(0)); } // Initialize the stack X // and string y as empty let X = []; let Y = "" ; // Loop to traverse string for (let i = 0; i < N; i++) { // If X is not empty and suff[i] // is greater than equal to top // character of stack X if (X.length > 0 && suff[i] >= X[X.length - 1].charCodeAt(0)) { Y += X[X.length - 1]; X.pop(); i--; } // If suff[i] is equal to S[i] else if (String.fromCharCode(suff[i]) == S[i]) { Y += S[i]; } // Otherwise push character // S[i] into the stack X else { X.push(S[i]); } } // Append all remaining characters // of X into string Y while (X.length > 0) { Y += X[X.length - 1]; X.pop(); } // Return Answer return Y; } // Driver Code let s = "acdb" ; document.write(smallestString(s)); // This code is contributed by Potta Lokesh </script> |
abdc
Time Complexity: O(N)
Auxiliary Space: O(N)
Please Login to comment...