Skip to content
Related Articles

Related Articles

Minimize steps to form string S from any random string of length K using a fixed length subsequences

Improve Article
Save Article
  • Last Updated : 11 Oct, 2022
Improve Article
Save Article

Given a string S consisting of N characters and a positive integer K, the task is to find the minimum number of operations required to generate the string S from a random string temp of size K and inserting the subsequence of any fixed length from the random string in the random string. If it is impossible to generate the string S, then print “-1”.

Examples:

Input: S = “toffee”, K = 4
Output: 2 tofe
Explanation:
Consider the random string temp as “tofe” which is of length K(= 4) and perform the following steps:
Operation 1: Take a subsequence of length 1 from string temp as ‘f’ and after inserting the subsequence in the string “tofe” modifies the string to “toffe”.
Operation 2: Take a subsequence of length 1 from string temp as ‘e’ and after inserting the subsequence in the string “toffe” modifies the string to “toffee”.
Therefore, the minimum number of operations required is 2.

Input: S = “book”, K = 2
Output: -1

Approach: This problem can be solved by using Greedy Approach and Binary Search. Follow the steps below to solve this problem:

  • Initialize an array, say amounts[] that stores the frequency of each character of string S.
  • Iterate in the range [0, N – 1] using the variable i and increment the frequency of the current character by 1 in the array amounts[].
  • Find count unique characters in the string S and store it in a variable, say, count.
  • If the count is greater than N, then return -1.
  • Now, perform the Binary Search to find the resultant string and perform the following steps:
  • Initialize two variables high as 105 and low as 0.
  • Iterate until the value of (high – low) is greater than 1 and perform the following steps:
    • Update the value of total as 0 and mid as (high + low) / 2.
    • Iterate in the range [0, 25] using the variable i and if the value of amounts[i] is greater than 0, then increment the total by (amounts[i] – 1)/mid + 1.
    • If the total is less than equal to N, then update the value of high as mid. Otherwise, update the value of low as mid.
  • After completing the above steps, print the value of high and iterate in the range[0, 25], and print the resultant string.

Below is the implementation of the above approach:

C++




// C++ program for the above approach
#include <bits/stdc++.h>
using namespace std;
 
// Function to find the minimum number
// of string required to generate
// the original string
void findString(string S, int K)
{
    // Stores the frequency of each
    // character of String S
    int amounts[26];
 
    // Iterate over the range [0, 25]
    for (int i = 0; i < 26; i++) {
        amounts[i] = 0;
    }
 
    // Stores the frequency of each
    // character of String S
    for (int i = 0; i < S.length(); i++) {
        amounts[int(S[i]) - 97]++;
    }
 
    int count = 0;
 
    // Count unique characters in S
    for (int i = 0; i < 26; i++) {
        if (amounts[i] > 0)
            count++;
    }
 
    // If unique characters is greater
    // then N, then return -1
    if (count > K) {
        cout << "-1";
    }
 
    // Otherwise
    else {
 
        string ans = "";
        int high = 100001;
        int low = 0;
        int mid, total;
 
        // Perform Binary Search
        while ((high - low) > 1) {
 
            total = 0;
 
            // Find the value of mid
            mid = (high + low) / 2;
 
            // Iterate over the range
            // [0, 26]
            for (int i = 0; i < 26; i++) {
 
                // If the amount[i] is
                // greater than 0
                if (amounts[i] > 0) {
                    total += (amounts[i] - 1)
                                 / mid
                             + 1;
                }
            }
 
            // Update the ranges
            if (total <= K) {
                high = mid;
            }
            else {
                low = mid;
            }
        }
 
        cout << high << " ";
 
        total = 0;
 
        // Find the resultant string
        for (int i = 0; i < 26; i++) {
 
            if (amounts[i] > 0) {
                total += (amounts[i] - 1)
                             / high
                         + 1;
 
                for (int j = 0;
                     j < ((amounts[i] - 1)
                              / high
                          + 1);
                     j++) {
 
                    // Generate the subsequence
                    ans += char(i + 97);
                }
            }
        }
 
        // If the length of resultant
        // string is less than N than
        // add a character 'a'
        for (int i = total; i < K; i++) {
            ans += 'a';
        }
 
        reverse(ans.begin(), ans.end());
 
        // Print the string
        cout << ans;
    }
}
 
// Driver Code
int main()
{
    string S = "toffee";
    int K = 4;
    findString(S, K);
 
    return 0;
}

Java




// Java code for above approach
import java.util.*;
 
class GFG{
 
// Function to find the minimum number
// of string required to generate
// the original string
static void findString(String S, int N)
{
   
    // Stores the frequency of each
    // character of string S
    int[] amounts = new int[26];
 
    // Iterate over the range [0, 25]
    for (int i = 0; i < 26; i++) {
        amounts[i] = 0;
    }
 
    // Stores the frequency of each
    // character of string S
    for (int i = 0; i < S.length(); i++) {
        amounts[(int)(S.charAt(i) - 97)]++;
    }
 
    int count = 0;
 
    // Count unique characters in S
    for (int i = 0; i < 26; i++) {
        if (amounts[i] > 0)
            count++;
    }
 
    // If unique characters is greater
    // then N, then return -1
    if (count > N) {
        System.out.print("-1");
    }
 
    // Otherwise
    else {
 
        String ans = "";
        int high = 100001;
        int low = 0;
        int mid, total;
 
        // Perform Binary Search
        while ((high - low) > 1) {
 
            total = 0;
 
            // Find the value of mid
            mid = (high + low) / 2;
 
            // Iterate over the range
            // [0, 26]
            for (int i = 0; i < 26; i++) {
 
                // If the amount[i] is
                // greater than 0
                if (amounts[i] > 0) {
                    total += (amounts[i] - 1)
                                 / mid
                             + 1;
                }
            }
 
            // Update the ranges
            if (total <= N) {
                high = mid;
            }
            else {
                low = mid;
            }
        }
 
        System.out.print(high + " ");
 
        total = 0;
 
        // Find the resultant string
        for (int i = 0; i < 26; i++) {
 
            if (amounts[i] > 0) {
                total += (amounts[i] - 1)
                             / high
                         + 1;
 
                for (int j = 0;
                     j < ((amounts[i] - 1)
                              / high
                          + 1);
                     j++) {
 
                    // Generate the subsequence
                    ans += (char)(i + 97);
                }
            }
        }
 
        // If the length of resultant
        // string is less than N than
        // add a character 'a'
        for (int i = total; i < N; i++) {
            ans += 'a';
        }
         
        String reverse = "";
        int Len = ans.length() - 1
            while(Len >= 0
            
                reverse = reverse + ans.charAt(Len); 
                Len--; 
            }
 
        // Print the string
        System.out.print(reverse);
    }
}
 
// Driver Code
public static void main(String[] args)
{
    String S = "toffee";
    int K = 4;
    findString(S, K);
}
}
 
// This code is contributed by target_2.

Python3




# Python3 program for the above approach
 
# Function to find the minimum number
# of string required to generate
# the original string
def findString(S, N):
     
    # Stores the frequency of each
    # character of String S
    amounts = [0] * 26
     
    # Stores the frequency of each
    # character of String S
    for i in range(len(S)):
        amounts[ord(S[i]) - 97] += 1
         
    count = 0
     
    # Count unique characters in S
    for i in range(26):
        if amounts[i] > 0:
            count += 1
             
    # If unique characters is greater
    # then N, then return -1
    if count > N:
        print("-1")
         
    # Otherwise
    else:
        ans = ""
        high = 100001
        low = 0
         
        # Perform Binary Search
        while (high - low) > 1:
            total = 0
             
            # Find the value of mid
            mid = (high + low) // 2
             
            # Iterate over the range
            # [0, 26]
            for i in range(26):
                 
                # If the amount[i] is
                # greater than 0
                if amounts[i] > 0:
                    total += (amounts[i] - 1) // mid + 1
                     
            # Update the ranges
            if total <= N:
                high = mid
            else:
                low = mid
                 
        print(high, end = " ")
        total = 0
         
        # Find the resultant string
        for i in range(26):
            if amounts[i] > 0:
                total += (amounts[i] - 1) // high + 1
                for j in range((amounts[i] - 1) // high + 1):
                    ans += chr(i + 97)
         
        # If the length of resultant
        # string is less than N than
        # add a character 'a'            
        for i in range(total, N):
            ans += 'a'
             
        ans = ans[::-1]
         
        # Print the string
        print(ans)
 
# Driver code
S = "toffee"
K = 4
 
findString(S, K)
 
# This code is contributed by Parth Manchanda

C#




// C# program for the above approach
using System;
 
class GFG{
     
// Function to find the minimum number
// of string required to generate
// the original string
static void findString(string S, int N)
{
   
    // Stores the frequency of each
    // character of string S
    int[] amounts = new int[26];
 
    // Iterate over the range [0, 25]
    for (int i = 0; i < 26; i++) {
        amounts[i] = 0;
    }
 
    // Stores the frequency of each
    // character of string S
    for (int i = 0; i < S.Length; i++) {
        amounts[(int)(S[i] - 97)]++;
    }
 
    int count = 0;
 
    // Count unique characters in S
    for (int i = 0; i < 26; i++) {
        if (amounts[i] > 0)
            count++;
    }
 
    // If unique characters is greater
    // then N, then return -1
    if (count > N) {
        Console.Write("-1");
    }
 
    // Otherwise
    else {
 
        string ans = "";
        int high = 100001;
        int low = 0;
        int mid, total;
 
        // Perform Binary Search
        while ((high - low) > 1) {
 
            total = 0;
 
            // Find the value of mid
            mid = (high + low) / 2;
 
            // Iterate over the range
            // [0, 26]
            for (int i = 0; i < 26; i++) {
 
                // If the amount[i] is
                // greater than 0
                if (amounts[i] > 0) {
                    total += (amounts[i] - 1)
                                 / mid
                             + 1;
                }
            }
 
            // Update the ranges
            if (total <= N) {
                high = mid;
            }
            else {
                low = mid;
            }
        }
 
        Console.Write(high + " ");
 
        total = 0;
 
        // Find the resultant string
        for (int i = 0; i < 26; i++) {
 
            if (amounts[i] > 0) {
                total += (amounts[i] - 1)
                             / high
                         + 1;
 
                for (int j = 0;
                     j < ((amounts[i] - 1)
                              / high
                          + 1);
                     j++) {
 
                    // Generate the subsequence
                    ans += (char)(i + 97);
                }
            }
        }
 
        // If the length of resultant
        // string is less than N than
        // add a character 'a'
        for (int i = total; i < N; i++) {
            ans += 'a';
        }
         
        string reverse = "";
        int Len = ans.Length - 1; 
            while(Len >= 0) 
            
                reverse = reverse + ans[Len]; 
                Len--; 
            }
 
        // Print the string
        Console.Write(reverse);
    }
}
 
// Driver Code
public static void Main()
{
    string S = "toffee";
    int K = 4;
    findString(S, K);
}
}
 
// This code is contributed by splevel62.

Javascript




<script>
// Javascript program for the above approach
 
// Function to find the minimum number
// of string required to generate
// the original string
function findString(S, N)
{
 
  // Stores the frequency of each
  // character of String S
  let amounts = new Array(26);
 
  // Iterate over the range [0, 25]
  for (let i = 0; i < 26; i++) {
    amounts[i] = 0;
  }
 
  // Stores the frequency of each
  // character of String S
  for (let i = 0; i < S.length; i++) {
    amounts[S[i].charCodeAt(0) - 97]++;
  }
 
  let count = 0;
 
  // Count unique characters in S
  for (let i = 0; i < 26; i++) {
    if (amounts[i] > 0) count++;
  }
 
  // If unique characters is greater
  // then N, then return -1
  if (count > N) {
    document.write("-1");
  }
 
  // Otherwise
  else {
    let ans = "";
    let high = 100001;
    let low = 0;
    let mid, total;
 
    // Perform Binary Search
    while (high - low > 1) {
      total = 0;
 
      // Find the value of mid
      mid = Math.floor((high + low) / 2);
 
      // Iterate over the range
      // [0, 26]
      for (let i = 0; i < 26; i++) {
        // If the amount[i] is
        // greater than 0
        if (amounts[i] > 0) {
          total += Math.floor((amounts[i] - 1) / mid + 1);
        }
      }
 
      // Update the ranges
      if (total <= N) {
        high = mid;
      } else {
        low = mid;
      }
    }
 
    document.write(high + " ");
 
    total = 0;
 
    // Find the resultant string
    for (let i = 0; i < 26; i++) {
      if (amounts[i] > 0) {
        total += Math.floor((amounts[i] - 1) / high + 1);
 
        for (let j = 0; j < Math.floor((amounts[i] - 1) / high + 1); j++) {
          // Generate the subsequence
          ans += String.fromCharCode(i + 97);
        }
      }
    }
 
    // If the length of resultant
    // string is less than N than
    // add a character 'a'
    for (let i = total; i < N; i++) {
      ans += "a";
    }
 
    ans =  ans.split("").reverse().join("");
 
    // Print the string
    document.write(ans);
  }
}
 
// Driver Code
 
let S = "toffee";
let K = 4;
findString(S, K);
 
// This code is contributed by _saurabh_jaiswal.
</script>

Output: 

2 tofe

 

Time Complexity: O(N), where N is the length of the given string.
Auxiliary Space: O(K), for storing a string of length K.


My Personal Notes arrow_drop_up
Related Articles

Start Your Coding Journey Now!