Open In App

Count number of substrings having at least K distinct characters

Improve
Improve
Like Article
Like
Save
Share
Report

Given a string S consisting of N characters and a positive integer K, the task is to count the number of substrings having at least K distinct characters.

Examples:

Input: S = “abcca”, K = 3
Output: 4
Explanation:
The substrings that contain at least K(= 3) distinct characters are:

  1. “abc”: Count of distinct characters = 3.
  2. “abcc”: Count of distinct characters = 3.
  3. “abcca”: Count of distinct characters = 3.
  4. “bcca”: Count of distinct characters = 3.

Therefore, the total count of substrings is 4.

Input: S = “abcca”, K = 4
Output: 0

Naive Approach: The simplest approach to solve the given problem is to generate all substrings of the given string and count those substrings that have at least K distinct characters in them. After checking for all the substrings, print the total count obtained as the result. 

Time Complexity: O(N3)
Auxiliary Space: O(1)

Efficient Approach: The above approach can also be optimized by using the concept of Sliding Window and Hashing. Follow the steps below to solve the problem:

  • Initialize a variable, say ans as 0 to store the count of substrings having at least K distinct characters.
  • Initialize two pointers, begin and end to store the starting and ending point of the sliding window.
  • Initialize a HashMap, say M to store the frequency of characters in the window.
  • Iterate until end is less than N, and perform the following steps:
    • Include the character at the end of the window, by incrementing the value of S[end] in M by 1.
    • Iterate until the size of M becomes less than K, and perform the following steps:
      • Remove the characters from the start of the window by decrementing the value of S[begin] in M by 1.
      • If its frequency becomes 0, then erase it from the map M.
      • Count all the substrings starting from begin till N by incrementing ans by (N – end + 1).
  • After completing the above steps, print the value of ans as the result.

Below is the implementation of the above approach:

C++




// C++ program for the above approach
 
#include <bits/stdc++.h>
using namespace std;
 
// Function to count number of substrings
// having atleast k distinct characters
void atleastkDistinctChars(string s, int k)
{
    // Stores the size of the string
    int n = s.size();
 
    // Initialize a HashMap
    unordered_map<char, int> mp;
 
    // Stores the start and end
    // indices of sliding window
    int begin = 0, end = 0;
 
    // Stores the required result
    int ans = 0;
 
    // Iterate while the end
    // pointer is less than n
    while (end < n) {
 
        // Include the character at
        // the end of the window
        char ch = s[end];
        mp[ch]++;
 
        // Increment end pointer by 1
        end++;
 
        // Iterate until count of distinct
        // characters becomes less than K
        while (mp.size() >= k) {
 
            // Remove the character from
            // the beginning of window
            char pre = s[begin];
            mp[pre]--;
 
            // If its frequency is 0,
            // remove it from the map
            if (mp[pre] == 0) {
                mp.erase(pre);
            }
 
            // Update the answer
            ans += s.length() - end + 1;
            begin++;
        }
    }
 
    // Print the result
    cout << ans;
}
 
// Driver Code
int main()
{
    string S = "abcca";
    int K = 3;
    atleastkDistinctChars(S, K);
 
    return 0;
}


Java




// Java program for the above approach
import java.util.*;
class GFG
{
   
// Function to count number of substrings
// having atleast k distinct characters
static void atleastkDistinctChars(String s, int k)
{
   
    // Stores the size of the string
    int n = s.length();
 
    // Initialize a HashMap
    Map<Character, Integer> mp = new HashMap<>();
 
    // Stores the start and end
    // indices of sliding window
    int begin = 0, end = 0;
 
    // Stores the required result
    int ans = 0;
 
    // Iterate while the end
    // pointer is less than n
    while (end < n) {
 
        // Include the character at
        // the end of the window
        char c = s.charAt(end);
        mp.put(c,mp.getOrDefault(c,0)+1);
 
        // Increment end pointer by 1
        end++;
 
        // Iterate until count of distinct
        // characters becomes less than K
        while (mp.size() >= k) {
 
            // Remove the character from
            // the beginning of window
            char pre = s.charAt(begin);
            mp.put(pre,mp.getOrDefault(pre,0)-1);
 
            // If its frequency is 0,
            // remove it from the map
            if (mp.get(pre)==0){
                mp.remove(pre);
            }
 
            // Update the answer
            ans += s.length() - end + 1;
            begin++;
        }
    }
 
    // Print the result
    System.out.println(ans);
}
   
  // Driver code
public static void main (String[] args)
{
   
      // Given inputs
    String S = "abcca";
    int K = 3;
    atleastkDistinctChars(S, K);
 
    }
}
 
// This code is contributed by offbeat


Python3




# Python 3 program for the above approach
from collections import defaultdict
 
# Function to count number of substrings
# having atleast k distinct characters
def atleastkDistinctChars(s, k):
 
    # Stores the size of the string
    n = len(s)
 
    # Initialize a HashMap
    mp = defaultdict(int)
 
    # Stores the start and end
    # indices of sliding window
    begin = 0
    end = 0
 
    # Stores the required result
    ans = 0
 
    # Iterate while the end
    # pointer is less than n
    while (end < n):
 
        # Include the character at
        # the end of the window
        c = s[end]
        mp += 1
 
        # Increment end pointer by 1
        end += 1
 
        # Iterate until count of distinct
        # characters becomes less than K
        while (len(mp) >= k):
 
            # Remove the character from
            # the beginning of window
            pre = s[begin]
            mp[pre] -= 1
 
            # If its frequency is 0,
            # remove it from the map
            if (mp[pre] == 0):
                del mp[pre]
 
            # Update the answer
            ans += len(s) - end + 1
            begin += 1
 
    # Print the result
    print(ans)
 
 
# Driver Code
if __name__ == "__main__":
 
    S = "abcca"
    K = 3
    atleastkDistinctChars(S, K)
 
    # This code is contributed by ukasp.


C#




// C# program for the above approach
using System;
using System.Collections.Generic;
 
class GFG{
   
// Function to count number of substrings
// having atleast k distinct characters
static void atleastkDistinctChars(string s, int k)
{
     
    // Stores the size of the string
    int n = s.Length;
 
    // Initialize a HashMap
    Dictionary<char,
               int> mp = new Dictionary<char,
                                        int>();
 
    // Stores the start and end
    // indices of sliding window
    int begin = 0, end = 0;
 
    // Stores the required result
    int ans = 0;
 
    // Iterate while the end
    // pointer is less than n
    while (end < n)
    {
         
        // Include the character at
        // the end of the window
        char c = s[end];
        if (mp.ContainsKey(c))
            mp++;
        else
            mp.Add(c, 1);
 
        // Increment end pointer by 1
        end++;
 
        // Iterate until count of distinct
        // characters becomes less than K
        while (mp.Count >= k)
        {
             
            // Remove the character from
            // the beginning of window
            char pre = s[begin];
            mp[pre]--;
 
            // If its frequency is 0,
            // remove it from the map
            if (mp[pre] == 0)
            {
                mp.Remove(pre);
            }
 
            // Update the answer
            ans += s.Length - end + 1;
            begin++;
        }
    }
 
    // Print the result
    Console.Write(ans);
}
 
// Driver Code
public static void Main()
{
    string S = "abcca";
    int K = 3;
     
    atleastkDistinctChars(S, K);
}
}
 
// This code is contributed by bgangwar59


Javascript




<script>
// Javascript program for the above approach
     
    // Function to count number of substrings
// having atleast k distinct characters
    function atleastkDistinctChars(s,k)
    {
        // Stores the size of the string
    let n = s.length;
  
    // Initialize a HashMap
    let mp = new Map();
  
    // Stores the start and end
    // indices of sliding window
    let begin = 0, end = 0;
  
    // Stores the required result
    let ans = 0;
  
    // Iterate while the end
    // pointer is less than n
    while (end < n)
    {
          
        // Include the character at
        // the end of the window
        let c = s[end];
        if (mp.has(c))
            mp.set(c,mp.get(c)+1);
        else
            mp.set(c, 1);
  
        // Increment end pointer by 1
        end++;
          
        // Iterate until count of distinct
        // characters becomes less than K
        while (mp.size >= k)
        {
              
            // Remove the character from
            // the beginning of window
            let pre = s[begin];
            mp.set(pre,mp.get(pre)-1);
  
            // If its frequency is 0,
            // remove it from the map
            if (mp.get(pre) == 0)
            {
                mp.delete(pre);
            }
  
            // Update the answer
            ans += s.length - end + 1;
            begin++;
        }
    }
  
    // Print the result
    document.write(ans);
    }
     
    // Driver Code
    let S = "abcca";
    let K = 3;
    atleastkDistinctChars(S, K);
 
 
 
// This code is contributed by rag2127
</script>


Output: 

4

 

Time Complexity: O(N)
Auxiliary Space: O(k)



Last Updated : 28 Dec, 2022
Like Article
Save Article
Previous
Next
Share your thoughts in the comments
Similar Reads