Given an array of strings, where each string consists of lowercase characters from a to j. You need to find the maximum number of strings that can be concatenated together such that the resulting string can be made out of exactly k distinct characters.
Example:
Input: n = 4, str = [ "abc", "de", "fg", "h"], k = 5
Output: 3
Explanation: The strings de, fg and h would add up to defgh which has exactly 5 distinct characters.Input: n = 3, str = [ "abcde", "de", "fghi"], k = 5
Output: 2
Explanation: The strings "abcde" and "de" would add up to abcdede which has exactly 5 distinct characters.
Approach: This can be solved with the following idea:
The main idea is to use a bitmask approach. We'll represent each string as a bitmask where each bit corresponds to a character in the alphabet (a to j). If a bit is set, it means the corresponding character is present in the string. By manipulating these bitmasks and using bitwise operations, we can efficiently check if a set of strings can be concatenated to form a string with exactly k distinct characters.
Below are the steps involved:
- Create a map called masks to store bitmasks of all input strings.
- Iterate through each string in the input s and convert it into a bitmask. Set bits in the bitmask based on the characters present in the string.
- Initialize ans to 0. This variable will keep track of the maximum number of concatenated strings that satisfy the condition.
- Iterate through numbers from 0 to 1024 (2^10), representing possible combinations of characters (bitmasks) with up to 10 distinct characters (as there are 10 possible characters from 'a' to 'j').
- For each number in the iteration, check if it has exactly k set bits using the __builtin_popcount function. If it doesn't, move to the next number.
- Initialize temp and tans to 0. The temp will be used to combine bitmasks of strings, and tans will store the count of concatenated strings for the current bitmask.
- Iterate through the masks map and check if the current bitmask includes the bitmask of a string. If it does, set the corresponding bits in temp and add the count of that string to tans.
- Check if temp is equal to the current bitmask. If they match, it means that all required characters are present in the concatenated strings.
- Update ans with the maximum of its current value and tans if the bitmasks match.
- Return the final value of ans, which represents the maximum number of concatenated strings with exactly k distinct characters.
Below is the implementation of the code:
// C++ Implementation
#include <bits/stdc++.h>
using namespace std;
// Function to find minimum number of string to comcat
int GetMax(int n, int k, vector<string>& s)
{
// Initialze a map
map<int, int> masks;
int temp = 0;
// Iterate in vector s
for (auto str : s) {
temp = 0;
// Do OR of each character
for (auto ch : str) {
temp |= (1 << (ch - 'a'));
}
masks[temp]++;
}
// Iterate for 1024 as the bits
int ans = 0;
int tans = 0;
for (int it = 0; it <= 1024; it++) {
// Count of set bits in it
if (__builtin_popcount(it) == k) {
temp = 0;
tans = 0;
// Iterate in mask map
for (auto str : masks) {
if ((it & str.first) == str.first) {
temp = temp | str.first;
tans += str.second;
}
}
// Update the max
if (temp == it) {
ans = max(ans, tans);
}
}
}
// Return the maximum value
return ans;
}
// Driver code
int main()
{
int n = 3;
int k = 3;
vector<string> s = { "ab", "c", "dfec" };
// Function call
cout << GetMax(n, k, s);
return 0;
}
import java.util.HashMap;
import java.util.Map;
import java.util.Vector;
public class Main {
// Function to find the minimum number of strings to concatenate
static int getMax(int n, int k, Vector<String> s) {
// Initialize a map
Map<Integer, Integer> masks = new HashMap<>();
int temp = 0;
// Iterate in the vector s
for (String str : s) {
temp = 0;
// Do OR of each character
for (char ch : str.toCharArray()) {
temp |= (1 << (ch - 'a'));
}
masks.put(temp, masks.getOrDefault(temp, 0) + 1);
}
// Iterate for 1024 as the bits
int ans = 0;
int tans = 0;
for (int it = 0; it <= 1024; it++) {
// Count of set bits in it
if (Integer.bitCount(it) == k) {
temp = 0;
tans = 0;
// Iterate in mask map
for (Map.Entry<Integer, Integer> entry : masks.entrySet()) {
int strKey = entry.getKey();
int strValue = entry.getValue();
if ((it & strKey) == strKey) {
temp |= strKey;
tans += strValue;
}
}
// Update the max
if (temp == it) {
ans = Math.max(ans, tans);
}
}
}
// Return the maximum value
return ans;
}
// Driver code
public static void main(String[] args) {
int n = 3;
int k = 3;
Vector<String> s = new Vector<>();
s.add("ab");
s.add("c");
s.add("dfec");
// Function call
System.out.println(getMax(n, k, s));
}
}
// This code is contributed by rambabuguphka
def get_max(n, k, s):
# Initialize a dictionary
masks = {}
temp = 0
# Iterate in list s
for string in s:
temp = 0
# Do OR of each character
for char in string:
temp |= (1 << (ord(char) - ord('a')))
masks[temp] = masks.get(temp, 0) + 1
# Iterate for 1024 as the bits
ans = 0
tans = 0
for it in range(1025):
# Count of set bits in it
if bin(it).count('1') == k:
temp = 0
tans = 0
# Iterate in mask dictionary
for key, value in masks.items():
if (it & key) == key:
temp |= key
tans += value
# Update the max
if temp == it:
ans = max(ans, tans)
# Return the maximum value
return ans
# Driver code
if __name__ == "__main__":
n = 3
k = 3
s = ["ab", "c", "dfec"]
# Function call
print(get_max(n, k, s))
// C# Implementation
using System;
using System.Collections.Generic;
class GFG
{
// Function to find minimum number of strings to concatenate
static int GetMax(int n, int k, List<string> s)
{
// Initialize a dictionary
Dictionary<int, int> masks = new Dictionary<int, int>();
int temp = 0;
// Iterate in list s
foreach (var str in s)
{
temp = 0;
// Do OR of each character
foreach (char ch in str)
{
temp |= (1 << (ch - 'a'));
}
if (masks.ContainsKey(temp))
masks[temp]++;
else
masks.Add(temp, 1);
}
// Iterate for 1024 as the bits
int ans = 0;
int tans = 0;
for (int it = 0; it <= 1024; it++)
{
// Count of set bits in it
if (CountSetBits(it) == k)
{
temp = 0;
tans = 0;
// Iterate in mask map
foreach (var str in masks)
{
if ((it & str.Key) == str.Key)
{
temp |= str.Key;
tans += str.Value;
}
}
// Update the max
if (temp == it)
{
ans = Math.Max(ans, tans);
}
}
}
// Return the maximum value
return ans;
}
// Function to count set bits
static int CountSetBits(int n)
{
int count = 0;
while (n > 0)
{
count += n & 1;
n >>= 1;
}
return count;
}
// Driver code
static void Main(string[] args)
{
int n = 3;
int k = 3;
List<string> s = new List<string> { "ab", "c", "dfec" };
// Function call
Console.WriteLine(GetMax(n, k, s));
}
}
// Function to find minimum number of strings to concatenate
function getMax(n, k, s) {
// Initialize a map
const masks = new Map();
let temp = 0;
// Iterate over each string in array s
for (let str of s) {
temp = 0;
// Perform bitwise OR of each character
for (let ch of str) {
temp |= (1 << (ch.charCodeAt(0) - 'a'.charCodeAt(0)));
}
masks.set(temp, (masks.get(temp) || 0) + 1);
}
// Initialize variables for the maximum value
let ans = 0;
let tans = 0;
// Iterate up to 1024 as the bits
for (let it = 0; it <= 1024; it++) {
// Count the set bits in it
if (countSetBits(it) === k) {
temp = 0;
tans = 0;
// Iterate over the mask map
for (let [key, value] of masks.entries()) {
if ((it & key) === key) {
temp |= key;
tans += value;
}
}
// Update the maximum value
if (temp === it) {
ans = Math.max(ans, tans);
}
}
}
// Return the maximum value
return ans;
}
// Function to count the set bits
function countSetBits(n) {
let count = 0;
while (n) {
count += n & 1;
n >>= 1;
}
return count;
}
// Driver code
function main() {
const n = 3;
const k = 3;
const s = ["ab", "c", "dfec"];
// Function call
console.log(getMax(n, k, s));
}
// Invoke the main function
main();
// This code is contributed by shivamgupta310570
Output
2
Time Complexity: O(N)
Auxiliary Space: O(N), Where N is the number of strings present in the array.