Given a string S of length N containing small-case English alphabets and an integer K, the task is to find the maximum possible length of the subsequence of S such that:
- The frequency of each letter in the subsequence does not differ by more than K from the frequency of any other letter.
- For any letter L that appears at least once, all occurrences of L must form a continuous segment.
Examples:
Input: S = “abba” , K = 1
Output: 3
Explanation: Subsequence “abb” and “bba” satisfies both the conditions.Input: S = “aaa” , K = 2
Output: 3
Naive Approach: To solve the problem follow the below idea:
The brute force approach is to generate all subsequences and then check whether it meets all the conditions or not.
Follow the given steps to solve the given problem:
- Generate all subsequences for a given string.
- If the length of subsequence is greater than 0 then check whether equal characters are continuous or not (implemented as function isContinuous).
- Again check whether the difference between maximum frequency and minimum frequency is less than k or not.
- If the above two steps pass, then store the maximum length of all such subsequences. (say maxLen).
- Return the maximum length maxLen as the final answer.
// C++ code to implement this approach #include <bits/stdc++.h> using namespace std;
int maxLen = 0;
// Function to check whether all the // characters in the substring // are continuous or not bool isContinuous(string& temp)
{ unordered_map< char , int > last_Pos;
for ( int i = 0; i < temp.length(); i++) {
if (last_Pos[temp[i]]) {
if (i - last_Pos[temp[i]] + 1 <= 1)
last_Pos[temp[i]] = i + 1;
else
return 0;
}
else
last_Pos[temp[i]] = i + 1;
}
return 1;
} // Function to find the all the substrings void generateSubSequences(string& str, string temp, int j,
int & k)
{ unordered_map< char , int > freq;
if (j == str.length()) {
if (temp.length() > 0) {
int minfreq = INT_MAX, maxfreq = INT_MIN;
freq.clear();
for ( int i = 0; i < temp.length(); i++)
freq[temp[i]]++;
for ( auto & x : freq) {
minfreq = min(minfreq, x.second);
maxfreq = max(maxfreq, x.second);
}
if (maxfreq - minfreq <= k
&& isContinuous(temp))
maxLen = max(maxLen, ( int )temp.length());
}
return ;
}
generateSubSequences(str, temp, j + 1, k);
temp.push_back(str[j]);
generateSubSequences(str, temp, j + 1, k);
} // Driver's code int main()
{ string str = "abba" , temp;
int k = 1;
generateSubSequences(str, temp, 0, k);
cout << maxLen;
return 0;
} |
// Java code for the above approach import java.io.*;
import java.util.*;
class GFG {
static int maxLen = 0 ;
// Function to check whether all the characters in the
// substring are continuous or not
static boolean iscontinuous(String temp)
{
Map<Character, Integer> last_Pos = new HashMap<>();
for ( int i = 0 ; i < temp.length(); i++) {
if (last_Pos.containsKey(temp.charAt(i))) {
if (i - last_Pos.get(temp.charAt(i)) + 1
<= 1 ) {
last_Pos.put(
temp.charAt(i),
last_Pos.get(temp.charAt(i)) + 1 );
}
else {
return false ;
}
}
else {
last_Pos.put(
temp.charAt(i),
last_Pos.getOrDefault(temp.charAt(i), 0 )
+ 1 );
}
}
return true ;
}
// Function to find the all the substrings
static void generateSubSequences(String str,
String temp, int j,
int k)
{
HashMap<Character, Integer> freq = new HashMap<>();
if (j == str.length()) {
if (temp.length() > 0 ) {
int minfreq = Integer.MAX_VALUE,
maxfreq = Integer.MIN_VALUE;
freq.clear();
for ( int i = 0 ; i < temp.length(); i++) {
freq.put(
temp.charAt(i),
freq.getOrDefault(temp.charAt(i), 0 )
+ 1 );
}
for ( int i : freq.values()) {
minfreq = Math.min(minfreq, i);
maxfreq = Math.max(maxfreq, i);
}
if (maxfreq - minfreq <= k
&& iscontinuous(temp)) {
maxLen = Math.max(maxLen,
( int )temp.length());
}
}
return ;
}
generateSubSequences(str, temp, j + 1 , k);
temp += str.charAt(j);
generateSubSequences(str, temp, j + 1 , k);
}
public static void main(String[] args)
{
String str = "abba" , temp = "" ;
int k = 1 ;
generateSubSequences(str, temp, 0 , k);
System.out.print(maxLen);
}
} // This code is contributed by lokeshmvs21. |
# Python code to implement this approach maxLen = 0
# Function to check whether all the # characters in the substring # are continuous or not def isContinuous(temp):
last_Pos = {}
for i in range ( len (temp)):
if temp[i] in last_Pos:
if i - last_Pos[temp[i]] + 1 < = 1 :
last_Pos[temp[i]] = i + 1
else :
return False
else :
last_Pos[temp[i]] = i + 1
return True
# Function to find the all the substrings def generateSubSequences( str , temp, j, k):
freq = {}
if j = = len ( str ):
if len (temp) > 0 :
minfreq = float ( 'inf' )
maxfreq = float ( '-inf' )
freq.clear()
for i in range ( len (temp)):
if (temp[i] in freq):
freq[temp[i]] + = 1
else :
freq[temp[i]] = 1
for key, value in freq.items():
minfreq = min (minfreq, value)
maxfreq = max (maxfreq, value)
if maxfreq - minfreq < = k and isContinuous(temp):
global maxLen
maxLen = max (maxLen, len (temp))
return
generateSubSequences( str , temp, j + 1 , k)
temp + = str [j]
generateSubSequences( str , temp, j + 1 , k)
# Driver's code if __name__ = = '__main__' :
str = "abba"
temp = ""
k = 1
generateSubSequences( str , temp, 0 , k)
print (maxLen)
# This code is contributed by Tapesh(tapeshdua420) |
// Include namespace system using System;
using System.Collections.Generic;
using System.Collections;
public class GFG
{ public static int maxLen = 0;
// Function to check whether all the characters in the
// substring are continuous or not
public static bool iscontinuous(String temp)
{
var last_Pos = new Dictionary< char , int >();
for ( int i = 0; i < temp.Length; i++)
{
if (last_Pos.ContainsKey(temp[i]))
{
if (i - last_Pos[temp[i]] + 1 <= 1)
{
last_Pos[temp[i]] = last_Pos[temp[i]] + 1;
}
else
{
return false ;
}
}
else
{
last_Pos[temp[i]] = (last_Pos.ContainsKey(temp[i]) ? last_Pos[temp[i]] : 0) + 1;
}
}
return true ;
}
// Function to find the all the substrings
public static void generateSubSequences(String str, String temp, int j, int k)
{
var freq = new Dictionary< char , int >();
if (j == str.Length)
{
if (temp.Length > 0)
{
var minfreq = int .MaxValue;
var maxfreq = int .MinValue;
freq.Clear();
for ( int i = 0; i < temp.Length; i++)
{
freq[temp[i]] = (freq.ContainsKey(temp[i]) ? freq[temp[i]] : 0) + 1;
}
foreach ( int i in freq.Values)
{
minfreq = Math.Min(minfreq,i);
maxfreq = Math.Max(maxfreq,i);
}
if (maxfreq - minfreq <= k && GFG.iscontinuous(temp))
{
GFG.maxLen = Math.Max(GFG.maxLen,( int )temp.Length);
}
}
return ;
}
GFG.generateSubSequences(str, temp, j + 1, k);
temp += str[j];
GFG.generateSubSequences(str, temp, j + 1, k);
}
public static void Main(String[] args)
{
var str = "abba" ;
var temp = "" ;
var k = 1;
GFG.generateSubSequences(str, temp, 0, k);
Console.Write(GFG.maxLen);
}
} // This code is contributed by aadityaburujwale. |
// JS code to implement this approach let maxLen = 0; // Function to check whether all the // characters in the substring // are continuous or not function isContinuous(temp)
{ let last_Pos = new Map();
for (let i=97;i<=122;i++)
{
last_Pos.set(String.fromCharCode(i),0);
}
for (let i = 0; i < temp.length; i++) {
if (last_Pos.get(temp[i])) {
if (i - last_Pos.get(temp[i]) + 1 <= 1)
last_Pos.set(temp[i] , i + 1);
else
return 0;
}
else
last_Pos.set(temp[i] , i + 1);
}
return 1;
} // Function to find the all the substrings function generateSubSequences(str, temp, j, k)
{ let freq = new Map();
for (let i=97;i<=122;i++)
{
freq.set(String.fromCharCode(i), 0);
}
if (j == str.length) {
if (temp.length > 0) {
let minfreq = Number.MAX_VALUE, maxfreq = Number.MIN_VALUE;
freq.clear();
for (let i = 0; i < temp.length; i++)
freq[temp[i]]++;
for (let [key, value] of freq) {
minfreq = Math.min(minfreq, value);
maxfreq = Math.max(maxfreq, value);
}
if (maxfreq - minfreq <= k
&& isContinuous(temp))
maxLen = Math.max(maxLen, temp.length);
}
return ;
}
generateSubSequences(str, temp, j + 1, k);
temp+=str[j];
generateSubSequences(str, temp, j + 1, k);
} // Driver's code let str = "abba" , temp = "" ;
let k = 1; generateSubSequences(str, temp, 0, k); console.log(maxLen); // This code is contributed by akashish__. |
3
Time Complexity: O(N*2N)
Auxiliary Space: O(N)