Longest Subsequence with same char as substrings and difference of frequency at most K
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)
Please Login to comment...