Open In App

Lexicographically shortest valid Subset selection

Last Updated : 16 Sep, 2023
Improve
Improve
Like Article
Like
Save
Share
Report

Given an array A of size N containing strings in lowercase letters. You can pick different subsets from individual strings, but then each subset must be present in all strings, then only the subset is said to be valid. Choose the longest and lexicographically shortest subset of string from the array and print it out of that subset string or if not print -1.

Examples:

Input: N = 3, A = {{aaab}, {aab}, {baac}}
Output: aab
Explanation: The valid subsets are {aab}, {a}, {aa}, {aba}, {baa}, {}. Out of these, the longest and lexicographically shortest is “aab”.

Input: N = 5, A = {{bg}, {bggb}, {bbgg}, {c}, {gbgb}}
Output: -1
Explanation: The subset {c} can be found only in string {c} but this subset is not found elsewhere. Hence the output is -1. If the string {c} wasn’t present in array A then the answer would be {bg} out of the valid subsets {b}, {g}, {bg}.

Approach: This can be solved with the following idea:

The idea is to take the minimum count of each character of each string and print it in alphabetical order. To do this count the frequency of each character in each string and take the minimum of the frequency for each character for all strings. If the resulting string from the final frequency mapping is empty then print -1 otherwise print the string in the alphabetical order.

Below are the steps to solve the above approach:

  • Create a global bucket of size 26. Initialize it with the value N+1. Let’s call this bucket/array final_freq.
  • For each string find the character frequency and maintain it in the bucket/array freq of size 26.
  • Now to take the minimum iterate the bucket freq and perform final_freq = min(final_freq[i], freq[I]). This will maintain the minimum character count for each string thus enabling common character subsets in all strings.
  • Now to print the solution check if the final_freq array has all elements 0. If they are that means there exists a string which does not contain any subset that is common with other strings. Hence print -1.
  • Otherwise, iterate the final_freq array and print the characters in increasing order as per their frequency.

Below is the Implementation of the above approach:

C++




// C++ code for the above approach:
#include <bits/stdc++.h>
using namespace std;
 
void solve(int N, vector<string> A)
{
 
    // Initialize a vector to store the
    // minimum frequency of each letter
    vector<int> final_freq(26, N + 1);
 
    // Initialize a vector to store the
    // frequency of each letter
    vector<int> freq(26);
 
    // Iterate through each string
    // in the vector A
    for (string str : A) {
        // Count the frequency of each
        // letter in the current string
        for (char ch : str) {
            freq[ch - 'a']++;
        }
 
        // Update the minimum frequency
        // for each letter
        for (int i = 0; i < 26; i++) {
            final_freq[i] = min(final_freq[i], freq[i]);
        }
 
        // Reset the frequency vector
        // for the next string
        freq.assign(26, 0);
    }
 
    // Check if any letter has a minimum
    // frequency greater than 0
    bool flag = false;
    for (int i : final_freq) {
        if (i) {
            flag = true;
            break;
        }
    }
 
    // If no letter has a minimum
    // frequency greater than 0, print -1
    if (flag == false) {
        cout << "-1\n";
    }
    else {
 
        // Print the letters in
        // lexicographical order based
        // on their minimum frequency
        for (int i = 0; i < 26; i++) {
            int cnt = final_freq[i];
            while (cnt--) {
                cout << char('a' + i);
            }
        }
        cout << "\n";
    }
}
 
// Drivers code
int main()
{
    int N = 3;
    vector<string> A
        = { { "aaab" }, { "aab" }, { "baac" } };
 
    // Function Call
    solve(N, A);
    return 0;
}


Java




// Java code for the above approach:
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
 
public class GFG {
 
    public static void solve(int N, List<String> A) {
 
        // Initialize an array to store the
        // minimum frequency of each letter
        int[] final_freq = new int[26];
        Arrays.fill(final_freq, N + 1);
 
        // Initialize an array to store the
        // frequency of each letter
        int[] freq = new int[26];
 
        // Iterate through each string
        // in the list A
        for (String str : A) {
            // Count the frequency of each
            // letter in the current string
            for (char ch : str.toCharArray()) {
                freq[ch - 'a']++;
            }
 
            // Update the minimum frequency
            // for each letter
            for (int i = 0; i < 26; i++) {
                final_freq[i] = Math.min(final_freq[i], freq[i]);
            }
 
            // Reset the frequency array
            // for the next string
            Arrays.fill(freq, 0);
        }
 
        // Check if any letter has a minimum
        // frequency greater than 0
        boolean flag = false;
        for (int i : final_freq) {
            if (i > 0) {
                flag = true;
                break;
            }
        }
 
        // If no letter has a minimum
        // frequency greater than 0, print -1
        if (!flag) {
            System.out.println("-1");
        } else {
            // Print the letters in
            // lexicographical order based
            // on their minimum frequency
            for (int i = 0; i < 26; i++) {
                int cnt = final_freq[i];
                while (cnt-- > 0) {
                    System.out.print((char) ('a' + i));
                }
            }
            System.out.println();
        }
    }
   
    // Drivers code
    public static void main(String[] args) {
        int N = 3;
        List<String> A = new ArrayList<>(Arrays.asList("aaab", "aab", "baac"));
 
        // Function Call
        solve(N, A);
    }
}


Python3




def solve(N, A):
    # Initialize a list to store the minimum frequency of each letter
    final_freq = [N + 1] * 26
 
    # Initialize a list to store the frequency of each letter
    freq = [0] * 26
 
    # Iterate through each string in the list A
    for string in A:
        # Count the frequency of each letter in the current string
        for ch in string:
            freq[ord(ch) - ord('a')] += 1
 
        # Update the minimum frequency for each letter
        for i in range(26):
            final_freq[i] = min(final_freq[i], freq[i])
 
        # Reset the frequency list for the next string
        freq = [0] * 26
 
    # Check if any letter has a minimum frequency greater than 0
    flag = False
    for i in final_freq:
        if i > 0:
            flag = True
            break
 
    # If no letter has a minimum frequency greater than 0, print -1
    if not flag:
        print("-1")
    else:
        # Print the letters in lexicographical order based on their minimum frequency
        for i in range(26):
            cnt = final_freq[i]
            while cnt > 0:
                print(chr(ord('a') + i), end ="")
                cnt -= 1
        print()
 
 
# Example usage
N = 3
A = ["aaab", "aab", "baac"]
solve(N, A)


C#




// C# code for the above approach
using System;
using System.Collections.Generic;
 
public class GFG {
    public static void Solve(int N, List<string> A)
    {
        // Initialize an array to store the
        // minimum frequency of each letter
        int[] final_freq = new int[26];
        Array.Fill(final_freq, N + 1);
 
        // Initialize an array to store the
        // frequency of each letter
        int[] freq = new int[26];
 
        // Iterate through each string
        // in the list A
        foreach(string str in A)
        {
            // Count the frequency of each
            // letter in the current string
            foreach(char ch in str.ToCharArray())
            {
                freq[ch - 'a']++;
            }
 
            // Update the minimum frequency
            // for each letter
            for (int i = 0; i < 26; i++) {
                final_freq[i]
                    = Math.Min(final_freq[i], freq[i]);
            }
 
            // Reset the frequency array
            // for the next string
            Array.Fill(freq, 0);
        }
 
        // Check if any letter has a minimum
        // frequency greater than 0
        bool flag = false;
        foreach(int i in final_freq)
        {
            if (i > 0) {
                flag = true;
                break;
            }
        }
 
        // If no letter has a minimum
        // frequency greater than 0, print -1
        if (!flag) {
            Console.WriteLine("-1");
        }
        else {
            // Print the letters in
            // lexicographical order based
            // on their minimum frequency
            for (int i = 0; i < 26; i++) {
                int cnt = final_freq[i];
                while (cnt-- > 0) {
                    Console.Write((char)('a' + i));
                }
            }
            Console.WriteLine();
        }
    }
 
    // Drivers code
    public static void Main(string[] args)
    {
        int N = 3;
        List<string> A
            = new List<string>{ "aaab", "aab", "baac" };
 
        // Function Call
        Solve(N, A);
    }
}
 
// This code is contributed by Sakshi


Javascript




<script>
// JavaScript code for the above approach
 
function solve(N, A) {
    // Initialize an array to store the
    // minimum frequency of each letter
    let final_freq = new Array(26).fill(N + 1);
 
    // Initialize an array to store the
    // frequency of each letter
    let freq = new Array(26).fill(0);
 
    // Iterate through each string
    // in the array A
    for (let str of A) {
        // Count the frequency of each
        // letter in the current string
        for (let ch of str) {
            freq[ch.charCodeAt(0) - 'a'.charCodeAt(0)]++;
        }
 
        // Update the minimum frequency
        // for each letter
        for (let i = 0; i < 26; i++) {
            final_freq[i] = Math.min(final_freq[i], freq[i]);
        }
 
        // Reset the frequency array
        // for the next string
        freq.fill(0);
    }
 
    // Check if any letter has a minimum
    // frequency greater than 0
    let flag = false;
    for (let i of final_freq) {
        if (i) {
            flag = true;
            break;
        }
    }
 
    // If no letter has a minimum
    // frequency greater than 0, print -1
    if (!flag) {
        document.write("-1");
    } else {
        // Print the letters in
        // lexicographical order based
        // on their minimum frequency
        for (let i = 0; i < 26; i++) {
            let cnt = final_freq[i];
            while (cnt--) {
                document.write(String.fromCharCode('a'.charCodeAt(0) + i));
            }
        }
        document.write();
    }
}
 
// Driver code
let N = 3;
let A = ["aaab", "aab", "baac"];
 
// Function Call
solve(N, A);
 
// This code is contributed by Susobhan Akhuli
</script>


Output

aab

Time complexity: O(N * length of string)
Auxiliary Space: O(26) = O(1)



Like Article
Suggest improvement
Share your thoughts in the comments

Similar Reads