Open In App

Longest substring with atmost K characters from the given set of characters

Given a string S, an integer K and set of characters Q[], the task is to find the longest substring in string S which contains atmost K characters from the given character set Q[].
Examples: 
 

Input: S = “normal”, Q = {“a”, “o”, “n”, “m”, “r”, “l”}, K = 1 
Output: 1
Explanation: 
All the characters in the given string S are present in array. 
Therefore, we can select any substring of length 1.
Input: S = “giraffe”, Q = {“a”, “f”, “g”, “r”}, K = 2 
Output :
Explanation: 
Possible substrings with atmost 2 characters 
From the given set are {“gir”, “ira”, “ffe”} 
The maximum length of all the substrings is 3.



Approach: The idea is to use the concept of two pointers to consider the substrings of maximum length, such that it contains at most K character from the given set. Below is the illustration of the approach:
 

cur_max = max(cur_max, right - left)

Below is the implementation of the above approach:
 






// C++ implementation to find the
// longest substring in the string
// which contains atmost K characters
// from the given set of characters
 
#include <bits/stdc++.h>
 
using namespace std;
 
// Function to find the longest
// substring in the string
// which contains atmost K characters
// from the given set of characters
int maxNormalSubstring(string& P,
        set<char> Q, int K, int N)
{
 
    // Base Condition
    if (K == 0)
        return 0;
 
    // Count for Characters
    // from set in substring
    int count = 0;
     
    // Two pointers
    int left = 0, right = 0;
    int ans = 0;
 
    // Loop to iterate until
    // right pointer is not
    // equal to N
    while (right < N) {
         
        // Loop to increase the substring
        // length until the characters from
        // set are at most K
        while (right < N && count <= K) {
 
            // Check if current pointer
            // points a character from set
            if (Q.find(P[right]) != Q.end()){
                 
                // If the count of the
                // char is exceeding the limit
                if (count + 1 > K)
                    break;
                else
                    count++;
            }
 
            right++;
 
            // update answer with
            // substring length
            if (count <= K)
                ans = max(ans, right - left);
        }
         
        // Increment the left pointer until
        // the count is less than or equal to K
        while (left < right) {
            left++;
             
            // If the character which comes out is normal character
            // then decrement the count by 1
            if (Q.find(P[left-1]) != Q.end())
                count--;
 
            if (count < K)
                break;
        }
    }
 
    return ans;
}
 
// Driver Code
int main()
{
    string P = "giraffe";
    set<char> Q;
     
    // Construction of set
    Q.insert('a');
    Q.insert('f');
    Q.insert('g');
    Q.insert('r');
    int K = 2;
    int N = P.length();
 
    // output result
    cout << maxNormalSubstring(P, Q, K, N);
 
    return 0;
}




// Java implementation to find the
// longest substring in the string
// which contains atmost K characters
// from the given set of characters
import java.util.*;
 
class GFG{
     
// Function to find the longest
// substring in the string
// which contains atmost K characters
// from the given set of characters
static int maxNormalSubstring(String P,
                              Set<Character> Q,
                              int K, int N)
{
     
    // Base Condition
    if (K == 0)
        return 0;
 
    // Count for Characters
    // from set in substring
    int count = 0;
 
    // Two pointers
    int left = 0, right = 0;
    int ans = 0;
 
    // Loop to iterate until
    // right pointer is not
    // equal to N
    while (right < N)
    {
 
        // Loop to increase the substring
        // length until the characters from
        // set are at most K
        while (right < N && count <= K)
        {
 
            // Check if current pointer
            // points a character from set
            if (Q.contains(P.charAt(right)))
            {
                 
                // If the count of the
                // char is exceeding the limit
                if (count + 1 > K)
                    break;
                else
                    count++;
            }
            right++;
 
            // update answer with
            // substring length
            if (count <= K)
                ans = Math.max(ans, right - left);
        }
 
        // Increment the left pointer until
        // the count is less than or equal to K
        while (left < right)
        {
            left++;
 
            // If the character which comes out
            // then decrement the count by 1
            if (Q.contains(P.charAt(left-1)))
                count--;
            if (count < K)
                break;
        }
    }
    return ans;
}
 
// Driver code
public static void main(String[] args)
{
    String P = "giraffe";
    Set<Character> Q = new HashSet<>();
 
    // Construction of set
    Q.add('a');
    Q.add('f');
    Q.add('g');
    Q.add('r');
     
    int K = 2;
    int N = P.length();
 
    // Output result
    System.out.println(maxNormalSubstring(P, Q,
                                          K, N));
}
}
 
// This code is contributed by offbeat




# Python3 implementation to find the
# longest substring in the string
# which contains atmost K characters
# from the given set of characters
 
# Function to find the longest
# substring in the string
# which contains atmost K characters
# from the given set of characters
def maxNormalSubstring(P, Q, K, N):
 
    # Base Condition
    if (K == 0):
        return 0
 
    # Count for Characters
    # from set in substring
    count = 0
     
    # Two pointers
    left = 0
    right = 0
    ans = 0
 
    # Loop to iterate until
    # right pointer is not
    # equal to N
    while (right < N):
         
        # Loop to increase the substring
        # length until the characters from
        # set are at most K
        while (right < N and count <= K):
 
            # Check if current pointer
            # points a character from set
            if (P[right] in Q):
                 
                # If the count of the
                # char is exceeding the limit
                if (count + 1 > K):
                    break
                else:
                    count += 1
 
            right += 1
 
            # update answer with
            # substring length
            if (count <= K):
                ans = max(ans, right - left)
         
        # Increment the left pointer until
        # the count is less than or equal to K
        while (left < right):
            left += 1
             
            # If the character which comes out
            # then decrement the count by 1
            if (P[left-1] in Q):
                count -= 1
 
            if (count < K):
                break
 
    return ans
 
# Driver Code
P = "giraffe"
Q = {chr}
 
# Construction of set
Q.add('a')
Q.add('f')
Q.add('g')
Q.add('r')
K = 2
N = len(P)
 
# Output result
print(maxNormalSubstring(P, Q, K, N))
 
# This code is contributed by Sanjit_Prasad




// C# implementation to find the
// longest substring in the string
// which contains atmost K characters
// from the given set of characters
 
using System;
using System.Collections.Generic;
 
// Function to find the longest
// substring in the string
// which contains atmost K characters
// from the given set of characters
class Program {
  static int MaxNormalSubstring(string P, HashSet<char> Q, int K, int N) {
    // Base Condition
    if (K == 0) {
      return 0;
    }
 
    // Count for Characters
    // from set in substring
    int count = 0;
     
    // Two pointers
    int left = 0;
    int right = 0;
    int ans = 0;
 
    // Loop to iterate until
    // right pointer is not
    // equal to N
    while (right < N) {
        // Loop to increase the substring
        // length until the characters from
        // set are at most K
      while (right < N && count <= K) {
          // Check if current pointer
            // points a character from set
        if (Q.Contains(P[right])) {
            // If the count of the
                // char is exceeding the limit
          if (count + 1 > K) {
            break;
          } else {
            count++;
          }
        }
        right++;
         
        // update answer with
        // substring length
        if (count <= K) {
          ans = Math.Max(ans, right - left);
        }
      }
 
      // Increment the left pointer until
      // the count is less than or equal to K
      while (left < right) {
        left++;
 
        // If the character which comes out
        // then decrement the count by 1
        if (Q.Contains(P[left - 1])) {
          count--;
        }
        if (count < K) {
          break;
        }
      }
    }
    return ans;
  }
 
// Driver code
  static void Main(string[] args) {
    string P = "giraffe";
    // Construction of set
    HashSet<char> Q = new HashSet<char> { 'a', 'f', 'g', 'r' };
    int K = 2;
    int N = P.Length;
     
    // Output result
    Console.WriteLine(MaxNormalSubstring(P, Q, K, N));
  }
}
 
// This code is contributed by Aman Kumar




<script>
 
// JavaScript implementation of above approach
 
// Function to find the longest
// substring in the string
// which contains atmost K characters
// from the given set of characters
function maxNormalSubstring(P, Q, K, N)
{
 
    // Base Condition
    if (K == 0)
        return 0;
 
    // Count for Characters
    // from set in substring
    let count = 0;
     
    // Two pointers
    let left = 0, right = 0;
    let ans = 0;
 
    // Loop to iterate until
    // right pointer is not
    // equal to N
    while (right < N) {
         
        // Loop to increase the substring
        // length until the characters from
        // set are at most K
        while (right < N && count <= K) {
 
            // Check if current pointer
            // points a character from set
            if (Q.has(P[right])){
                 
                // If the count of the
                // char is exceeding the limit
                if (count + 1 > K)
                    break;
                else
                    count++;
            }
 
            right++;
 
            // update answer with
            // substring length
            if (count <= K)
                ans = Math.max(ans, right - left);
        }
         
        // Increment the left pointer until
        // the count is less than or equal to K
        while (left < right) {
            left++;
             
            // If the character which comes out is normal character
            // then decrement the count by 1
            if (Q.has(P[left-1]))
                count--;
 
            if (count < K)
                break;
        }
    }
 
    return ans;
}
 
// Driver Code
 
let P = "giraffe"
let Q = new Set()
 
// Construction of set
Q.add('a')
Q.add('f')
Q.add('g')
Q.add('r')
let K = 2;
let N = P.length;
 
// output result
document.write(maxNormalSubstring(P, Q, K, N),"</br>");
 
// This code is contributed by shinjanpatra
 
</script>

Output
3

Performance Analysis: 
 


Article Tags :