Open in App
Not now

# Longest Subsequence with same char as substrings and difference of frequency at most K

• Difficulty Level : Hard
• Last Updated : 16 Dec, 2022

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++14

```// 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

```// 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.```

## Python3

```# 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)```

## C#

```// 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.```

## Javascript

```// 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__.```
Output

`3`

Time Complexity: O(N*2N)
Auxiliary Space: O(N)

My Personal Notes arrow_drop_up
Related Articles