Lexicographically Kth-smallest string having ‘a’ X times and ‘b’ Y times


Lexicographically Kth-smallest string having ‘a’ X times and ‘b’ Y times is a problem where we need to find the Kth smallest string that contains X number of ‘a’s and Y number of ‘b’s. The strings are arranged lexicographically which means that the smallest string comes first when we sort all the possible strings.

In this tutorial, we will discuss how to solve this problem using C++. We will start by understanding the problem statement in detail, followed by the algorithmic approach. We will then move on to implementing the solution in C++ using dynamic programming. The code will be explained in detail, along with the step-by-step approach to solving the problem. By the end of this tutorial, you will have a clear understanding of how to solve this problem and the implementation details in C++. So let’s get started!

Problem Statement

The objective is to identify the Kth smallest string in lexicographical order that consists of X instances of character 'a' and Y instances of character 'b'. The input for this problem is three non-negative integers X, Y, and K.

Sample Example 1

Input

X=2, Y=3, K=3

Output

abbab

Explanation: The lexicographically first three smallest strings with 2 'a's and 3 'b's are "aabbb", "ababb", and "abbab". Hence, the third lexicographically smallest string is "abbab".

Sample Example 2

Input

X=4, Y=3, K=4

Output

aaabbba

Explanation: The lexicographically fourth smallest string with 4 'a's and 3 'b's is "aaabbba".

Algorithm

STEP 1. Create a function ‘fillDpArray’ that takes parameters ‘X’, ‘Y’, ‘dp[][MAX]’, ‘rows’, and ‘cols’:

  • Use ‘memset’ to fill the entire ‘dp’ array with 0s.

  • Set ‘dp[0][0]’ to 1.

  • Use nested loops to traverse the ‘dp’ array:

    • For each element ‘dp[i][j]’, update its value by adding the values of ‘dp[i - 1][j]’ and ‘dp[i][j - 1]’.

STEP 2. Create a recursive function ‘findKthString’ that takes parameters ‘X’, ‘Y’, ‘K’, and ‘dp[][MAX]’:

  • Handle the base cases:

    • If ‘X’ is 0, return a string of 'b' characters with length ‘Y’.

    • If ‘Y’ is 0, return a string of 'a' characters with length ‘X’.

  • Check if ‘K’ is less than or equal to ‘dp[X - 1][Y]’:

    • If true, return the concatenation of the character 'a' and the result of calling ‘findKthString’ with arguments ‘X - 1’, ‘Y’, ‘K’, and ‘dp’.

  • Otherwise:

    • Return the concatenation of the character 'b' and the result of calling findKthString with arguments ‘X’, ‘Y - 1’, ‘K - dp[X - 1][Y]’, and ‘dp’.

STEP 3. In the ‘main’ function:

  • Declare variables ‘X’, ‘Y’, and ‘K’ to store user input.

  • Read input values for ‘X’, ‘Y’, and ‘K’ from the user.

  • Validate the input values to ensure they meet the required criteria ‘(X >= 0, Y >= 0, and K > 0)’.

  • Create a 2D array ‘dp[MAX][MAX]’.

  • If the input values are valid, call the ‘fillDpArray’ function with arguments ‘X’, ‘Y’, ‘dp’, ‘MAX’, and ‘MAX’ to calculate the ‘dp’ array.

  • Check if the input values are valid and ‘K’ is less than or equal to ‘dp[X][Y]’:

    • If true, call the findKthString function with arguments ‘X’, ‘Y’, ‘K’, and ‘dp’ to get the Kth lexicographically smallest string.

    • Display the outcome by printing the string obtained from ‘findKthString’.

  • Otherwise, display an error message indicating invalid input values.

Now, let’s see the implementation of the above algorithm using C++ with the help of an example.

Example

Implementation of the above algorithm using C++

The below C++ program calculates the lexicographically Kth smallest string consisting of 'a's and 'b's. It uses dynamic programming to fill a 2D array, ‘dp’, with the count of valid strings for each combination of 'a's and 'b's. The ‘fillDpArray’ function initializes the array and updates its values based on previous values. The ‘findKthString’ function recursively constructs the Kth string by checking the count of strings starting with 'a' in ‘dp’ and recursively calling itself with updated values. The main function reads input values, validates them, calculates the result using ‘fillDpArray’ if the input is valid, and displays the outcome or an error message.

#include <iostream>
#include <cstring>

const int MAX = 30;
// Function to fill a 2D dp array with 0s
void fillDpArray(int X, int Y, int dp[][MAX], int rows, int cols) {
   memset(dp, 0, rows * cols * sizeof(int));
   dp[0][0] = 1;
   // Traverse the dp array and update its values
   for (int i = 0; i <= X; ++i) {
      for (int j = 0; j <= Y; ++j) {
         // Update the value of dp[i][j] based on previous values
         if (i > 0) {
            dp[i][j] += dp[i - 1][j];
         }
         if (j > 0) {
            dp[i][j] += dp[i][j - 1];
         }
      }
   }
}
// Recursive function to find the Kth lexicographically smallest string
std::string findKthString(int X, int Y, int K, int dp[][MAX]) {
   // Handle base cases where the string has only one character
   if (X == 0) {
      return std::string(Y, 'b');
   }
   if (Y == 0) {
      return std::string(X, 'a');
   }
   // If there are more than or equal to K strings which start with 'a',
   //Then the first character is 'a'
   if (K <= dp[X - 1][Y]) {
      return std::string("a") + findKthString(X - 1, Y, K, dp);
   }
   // Otherwise, the first character of the resultant string is 'b'
   else {
      return std::string("b") + findKthString(X, Y - 1, K - dp[X - 1][Y], dp);
   }
}
int main() {
   // Input variables
   int X=4, Y=3, K=4;
   // Validate the input values to ensure they meet the required criteria
   bool isValid = X >= 0 && Y >= 0 && K > 0;
   // Calculate the result
   int dp[MAX][MAX];
   if (isValid) {
      fillDpArray(X, Y, dp, MAX, MAX);
   }
   // Display the outcome or an error message
   if (isValid && K <= dp[X][Y]) {
      std::string kthString = findKthString(X, Y, K, dp);
      std::cout << "The " << K << "th lexicographically smallest string with " << X << " 'a's and " << Y << " 'b's is: " << kthString << std::endl;
   } else {
      std::cout << "Invalid input values. Please enter non-negative integers for 'a's and 'b's, and a positive integer for K." << std::endl;
   }
   return 0;
}

Output

The 4th lexicographically smallest string with 4 'a's and 3 'b's is: aaabbba

Conclusion

To sum up, finding the Kth lexicographically smallest string with given numbers of 'a's and 'b's requires the use of dynamic programming. By filling a 2D DP array and using a recursive function, we can find the Kth lexicographically smallest string. The time complexity of this algorithm is O(X * Y), where X and Y are the numbers of 'a's and 'b's respectively. This algorithm can be applied to a variety of problems that require finding the Kth lexicographically smallest string.

Updated on: 08-Sep-2023

60 Views

Kickstart Your Career

Get certified by completing the course

Get Started
Advertisements