Open In App

Minimize Set Cost

Last Updated : 28 Jan, 2024
Improve
Improve
Like Article
Like
Save
Share
Report

Given a string s of size n. In one move you can take any subsequence of the given string and add it to the set S. The set S can’t contain duplicates. The move costs n−|t|, where |t| is the length of the added subsequence. The task is to find out the minimum possible total cost to obtain a set S of size k.

Example:

Input: n = 4, k = 5, s = “asdf”
Output: 4

Input: n = 5, k = 6, s = aaaaa
Output: 15

Approach:

This problem can be approached using Breadth-First Search (BFS). Consider each string as a vertex in the graph, and there exists a directed edge from string s to string t if and only if t can be obtained from s by removing exactly one character.

In this context, the goal is to find the first k visited vertices when starting the BFS from the initial string. The minimum total cost is then calculated as nk minus the sum of the lengths of the visited strings. It is essential to use a queue of strings instead of integers for BFS, and maintain a set of visited strings instead of an array of visited vertices. The BFS process should terminate when exactly k strings are obtained.

If the number of distinct subsequences is less than k, the answer is -1.

Follow the steps to solve the above problem:

  • Initialize the variable ans to 0.
  • Create a queue of strings (q) for BFS.
  • Create a set of strings (st) to keep track of visited strings.
  • Push the initial string s to the queue and mark it as visited in the set.
  • Breadth-First Search (BFS):
    • While the queue is not empty and the set size is less than k:
      • Pop the front string (v) from the queue.
      • For each character in the string:
        • Create a new string by removing the character.
        • If the new string is not visited and the set size is less than k:
          • Push the new string to the queue, mark it as visited, and update ans.
  • If the set size is less than k, output -1.
  • Otherwise, output the final value of ans.

Below is the implementation of the above approach:

C++




#include <bits/stdc++.h>
 
using namespace std;
 
int main()
{
 
    // input
    int n = 4, k = 5;
    string s = "asdf";
 
    // Initialize the answer variable to 0
    int ans = 0;
 
    // Initialize a queue of strings for BFS
    queue<string> q;
 
    // Initialize a set to keep track of visited strings
    set<string> st;
 
    // Push the initial string to the queue and mark it as
    // visited
    q.push(s);
    st.insert(s);
 
    // Perform BFS until either the queue is empty or the
    // set size reaches k
    while (!q.empty() && int(st.size()) < k) {
        // Retrieve the front string from the queue
        string v = q.front();
        q.pop();
 
        // Iterate through each character of the string
        for (int i = 0; i < int(v.size()); ++i) {
            // Create a new string by removing the i-th
            // character
            string nv = v;
            nv.erase(i, 1);
 
            // Check if the new string is not visited and
            // the set size is less than k
            if (!st.count(nv) && int(st.size()) + 1 <= k) {
                // Push the new string to the queue, mark it
                // as visited, and update the answer
                q.push(nv);
                st.insert(nv);
                ans += n - nv.size();
            }
        }
    }
 
    // Check if the set size is less than k and output the
    // result
    if (int(st.size()) < k)
        cout << -1 << endl;
    else
        cout << ans << endl;
 
    return 0;
}


Java




// Java code for the above approach
 
import java.util.*;
 
class GFG {
 
    public static void main(String[] args)
    {
 
        // input
        int n = 4, k = 5;
        String s = "asdf";
 
        // Initialize the answer variable to 0
        int ans = 0;
 
        // Initialize a queue of strings for BFS
        Queue<String> q = new LinkedList<>();
 
        // Initialize a set to keep track of visited strings
        Set<String> st = new HashSet<>();
 
        // Push the initial string to the queue
        // and mark it as visited
        q.add(s);
        st.add(s);
 
        // Perform BFS until either the queue is
        // empty or the set size reaches k
        while (!q.isEmpty() && st.size() < k) {
            // Retrieve the front string from the queue
            String v = q.poll();
 
            // Iterate through each character of the string
            for (int i = 0; i < v.length(); ++i) {
                // Create a new string by removing the i-th
                // character
                String nv = v;
                nv = nv.substring(0, i)
                     + nv.substring(i + 1);
 
                // Check if the new string is not visited
                // and the set size is less than k
                if (!st.contains(nv)
                    && (st.size() + 1) <= k) {
                    // Push the new string to the queue,
                    // mark it as visited, and update the
                    // answer
                    q.add(nv);
                    st.add(nv);
                    ans += n - nv.length();
                }
            }
        }
 
        // Check if the set size is less than
        // k and output the result
        if (st.size() < k)
            System.out.println(-1);
        else
            System.out.println(ans);
    }
}
 
// This code is contributed by ragul21


Python3




from queue import Queue
 
# Perform BFS to find k distinct strings
def find_k_strings(n, k, s):
    # Initialize the answer variable to 0
    ans = 0
 
    # Initialize a queue of strings for BFS
    q = Queue()
 
    # Initialize a set to keep track of visited strings
    st = set()
 
    # Push the initial string to the queue and mark it as visited
    q.put(s)
    st.add(s)
 
    # Perform BFS until either the queue is empty or the set size reaches k
    while not q.empty() and len(st) < k:
        # Retrieve the front string from the queue
        v = q.get()
 
        # Iterate through each character of the string
        for i in range(len(v)):
            # Create a new string by removing the i-th character
            nv = v[:i] + v[i+1:]
 
            # Check if the new string is not visited and the set size is less than k
            if nv not in st and len(st) + 1 <= k:
                # Push the new string to the queue, mark it as visited, and update the answer
                q.put(nv)
                st.add(nv)
                ans += n - len(nv)
 
    # Check if the set size is less than k and output the result
    if len(st) < k:
        print(-1)
    else:
        print(ans)
 
# Input
n = 4
k = 5
s = "asdf"
 
# Call the function
find_k_strings(n, k, s)


C#




using System;
using System.Collections.Generic;
 
class GFG {
    public static void Main (string[] args) {
        // input
        int n = 4, k = 5;
        string s = "asdf";
 
        // Initialize the answer variable to 0
        int ans = 0;
 
        // Initialize a queue of strings for BFS
        Queue<string> q = new Queue<string>();
 
        // Initialize a set to keep track of visited strings
        HashSet<string> st = new HashSet<string>();
 
        // Push the initial string to the queue and mark it as
        // visited
        q.Enqueue(s);
        st.Add(s);
 
        // Perform BFS until either the queue is empty or the
        // set size reaches k
        while (q.Count > 0 && st.Count < k) {
            // Retrieve the front string from the queue
            string v = q.Dequeue();
 
            // Iterate through each character of the string
            for (int i = 0; i < v.Length; ++i) {
                // Create a new string by removing the i-th
                // character
                string nv = v.Remove(i, 1);
 
                // Check if the new string is not visited and
                // the set size is less than k
                if (!st.Contains(nv) && st.Count + 1 <= k) {
                    // Push the new string to the queue, mark it
                    // as visited, and update the answer
                    q.Enqueue(nv);
                    st.Add(nv);
                    ans += n - nv.Length;
                }
            }
        }
 
        // Check if the set size is less than k and output the
        // result
        if (st.Count < k)
            Console.WriteLine(-1);
        else
            Console.WriteLine(ans);
    }
}


Javascript




class Queue {
    constructor() {
        this.items = [];
    }
 
    enqueue(item) {
        this.items.push(item);
    }
 
    dequeue() {
        if (this.isEmpty()) {
            return null;
        }
        return this.items.shift();
    }
 
    isEmpty() {
        return this.items.length === 0;
    }
}
 
// Perform BFS to find k distinct strings
function findKStrings(n, k, s) {
    // Initialize the answer variable to 0
    let ans = 0;
 
    // Initialize a queue of strings for BFS
    let q = new Queue();
 
    // Initialize a set to keep track of visited strings
    let st = new Set();
 
    // Push the initial string to the queue and mark it as visited
    q.enqueue(s);
    st.add(s);
 
    // Perform BFS until either the queue is empty or the set size reaches k
    while (!q.isEmpty() && st.size < k) {
        // Retrieve the front string from the queue
        let v = q.dequeue();
 
        // Iterate through each character of the string
        for (let i = 0; i < v.length; i++) {
            // Create a new string by removing the i-th character
            let nv = v.slice(0, i) + v.slice(i + 1);
 
            // Check if the new string is not visited and
            // the set size is less than k
            if (!st.has(nv) && st.size + 1 <= k) {
                // Push the new string to the queue, mark it as visited,
                // and update the answer
                q.enqueue(nv);
                st.add(nv);
                ans += n - nv.length;
            }
        }
    }
 
    // Check if the set size is less than k and output the result
    if (st.size < k) {
        console.log(-1);
    } else {
        console.log(ans);
    }
}
 
// Input
let n = 4;
let k = 5;
let s = "asdf";
 
// Call the function
findKStrings(n, k, s);


Output

4


Time Complexity: O(n*n)
Auxiliary Space: O(n*n)



Like Article
Suggest improvement
Share your thoughts in the comments

Similar Reads