Longest Subsequence with Same Char as Substrings and Difference of Frequency at Most K


In this problem, we will find the maximum length of the subsequence such that it should contain the contiguous characters, and the frequency difference of all characters won’t differ more than K.

We need to find all possible subsequences of the given string and check whether it contains every character continuously and maximum frequency difference to get the output.

Problem statement− We have given a string alpha containing the lowercase alphabetical characters. Also, we have given the positive integer K. We need to find the maximum length of the subsequence of the given string such that it follows the below rules.

  • All occurrences of the particular character should be contiguous.

  • The difference of frequency of characters should not be more than K.

Sample examples

Input

alpha = "ppppqrs", K = 2

Output

6

Explanation − We can take the ‘pppqrs’ subsequence. The maximum character frequency is 3, and the minimum character frequency is 1. So, the difference is 2. Also, it contains all characters continuously.

Input

alpha = "abbbbc", K = 2

Output

5

Explanation − We can take the ‘abbbc’ subsequence.

Input

alpha = "mnnnnnnno", k = 3;

Output

7

Explanation − We can take the ‘nnnnnnn’ subsequence.

Approach 1

In this approach, we will use the recursive function to find all subsequences of the given length. Also, we will define the function to check whether the subsequence contains all characters continuously. We will use the map data structure to count the maximum and minimum frequency differences.

Algorithm

Step 1 − Define the ‘f’ map to store the frequency of characters.

Step 2 − If the start is equal to the temp string’s length, and the string length is greater than 0, follow the steps below.

Step 3 − Initialize the ‘minf’ and ‘maxf’ variables to store the minimum and maximum frequency.

Step 4 − Clear the map, and store each character’s frequency in the map.

Step 5 − Traverse the map values and find the maximum and minimum frequency values.

Step 6 − If the maximum and minimum frequency difference is less than or equal to K, check whether the string contains continuous characters.

Step 6.1 − In the checkForContinuous() function, define the ‘pos’ map to store the last position of the particular character.

Step 6.2 − Traverse the string. If Current characters exist in the map, and the difference between the current position and the last position of the character is less than 1, update the last position. Otherwise, return false.

Step 6.3 − Add a character to the map if the character doesn’t exist.

Step 6.4 − Return true at the end.

Step 7 − If the string contains the continuous character, and the frequency difference is less than K, update the value of the ‘maxi’ if it is less than the current subsequence’s length.

Step 8 − Make a recursive call after excluding the current character.

Step 9 − Append the current character at the end of the temp string. Also, make a recursive call with the updated ‘tmp’ string.

Example

#include <bits/stdc++.h>
using namespace std;

int maxi = 0;
// Check for continuous characters in the substring
bool CheckForContinuous(string &tmp) {
    // map to store the last index of the character
    unordered_map<char, int> pos;
    for (int p = 0; p < tmp.length(); p++) {
        // When the last index exists in the map
        if (pos[tmp[p]]) {
            // If the last index is adjacent to the current index
            if (p - pos[tmp[p]] + 1 <= 1)
                pos[tmp[p]] = p + 1;
            else
                return false;
        } else {
            // When the map doesn't have a character as a key
            pos[tmp[p]] = p + 1;
        }
    }
    return true;
}
void getLongestSubSeq(string &alpha, string tmp, int start, int &k) {
    // To store the character's frequency
    unordered_map<char, int> f;
    if (start == alpha.length()) {
        if (tmp.length() > 0) {
            // To store minimum and maximum frequency of characters
            int minf = INT_MAX, maxf = INT_MIN;
            // Make map empty
            f.clear();
            // Store frequency of characters in the map
            for (int p = 0; p < tmp.length(); p++)
                f[tmp[p]]++;

            // Get minimum and maximum value from the map
            for (auto &key : f) {
                minf = min(minf, key.second);
                maxf = max(maxf, key.second);
            }
            // Validate substring for frequency difference and continuous characters
            if (maxf - minf <= k && CheckForContinuous(tmp))
                maxi = max(maxi, (int)tmp.length());
        }
        return;
    }
    // Exclude current character
    getLongestSubSeq(alpha, tmp, start + 1, k);
    // Include current character
    tmp.push_back(alpha[start]);
    getLongestSubSeq(alpha, tmp, start + 1, k);
}
int main() {
    string alpha = "ppppqrs", tmp;
    int k = 2;
    getLongestSubSeq(alpha, tmp, 0, k);
    cout <<"The maximum length of the substring according to the given conditions is " << maxi;
    return 0;
}

Output

The maximum length of the substring according to the given conditions is 6

Time complexity − O(N*2N), where O(N) is to check for contiguous characters, and O(2N) for finding all subsequences.

Space complexity − O(N) to store the temporary subsequence.

We used the naïve approach to find all subsequences of the given string. However, it is very time expensive. Using this approach for large strings is not recommended to solve the problem.

Updated on: 17-Jul-2023

91 Views

Kickstart Your Career

Get certified by completing the course

Get Started
Advertisements