Open In App

Find lexicographical smallest string by performing the given operations N times

Last Updated : 22 Feb, 2022
Improve
Improve
Like Article
Like
Save
Share
Report

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:

  1. Perform operation 1. Hence, S = “ab”, X = “c”, Y = “”.
  2. Perform operation 1. Hence, S = “b”, X = “ca”, Y = “”.
  3. Perform operation 2. Hence, S = “b”, X = “c”, Y = “a”.
  4. Perform operation 1. Hence, S = “”, X = “cb”, Y = “a”.
  5. Perform operation 2. Hence, S = “”, X = “c”, Y = “ab”.
  6. 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>


 
 

Output

abdc

 

Time Complexity: O(N)
Auxiliary Space: O(N)

 



Like Article
Suggest improvement
Previous
Next
Share your thoughts in the comments

Similar Reads