Open In App

Count substrings with k distinct characters

Last Updated : 28 Mar, 2025
Comments
Improve
Suggest changes
Like Article
Like
Report

Given a string consisting of lowercase characters and an integer k, the task is to count all possible substrings (not necessarily distinct) that have exactly k distinct characters. 

Examples: 

Input: s = "abc", k = 2
Output: 2
Explanation: Possible substrings are {"ab", "bc"}

Input: s = "aba", k = 2
Output: 3
Explanation: Possible substrings are {"ab", "ba", "aba"}

Input: s = "aa", k = 1
Output: 3
Explanation: Possible substrings are {"a", "a", "aa"}

[Naive Approach] Checking all Substrings - O(n^2) time and O(1) space

The idea is to check every possible substring by iterating through all possible starting positions (i) and ending positions (j) in the string. For each substring, maintain a boolean vector to track distinct characters and a counter for the number of distinct characters. As it expands the substring from left to right, it updates the distinct character count by checking if each new character has been seen before. Whenever the number of distinct characters exactly matches the given k, it increments the answer count.

C++
// C++ program to find substrings 
// with K Distinct characters
#include <bits/stdc++.h>
using namespace std;

int countSubstr(string &s, int k) {
    int n = s.length();
    int ans = 0;
    
    for (int i=0; i<n; i++) {
        
        // Array to check if a character 
        // is present in substring i..j
        vector<bool> map(26, 0);
        int distinctCnt = 0;
        
        for (int j=i; j<n; j++) {
            
            // If new character is present,
            // increment distinct count.
            if (map[s[j] - 'a'] == false) {
                map[s[j] - 'a'] = true;
                distinctCnt++;
            }
            
            // If distinct count is equal to k.
            if (distinctCnt == k) ans++;
        }
    }
    
    return ans;
}

int main() {
    string s = "abc";
    int k = 2;
    cout << countSubstr(s, k);

    return 0;
}
Java
// Java program to find substrings 
// with K Distinct characters
import java.util.*;

class GfG {

    static int countSubstr(String s, int k) {
        int n = s.length();
        int ans = 0;

        for (int i = 0; i < n; i++) {

            // Array to check if a character 
            // is present in substring i..j
            boolean[] map = new boolean[26];
            int distinctCnt = 0;

            for (int j = i; j < n; j++) {

                // If new character is present,
                // increment distinct count.
                if (!map[s.charAt(j) - 'a']) {
                    map[s.charAt(j) - 'a'] = true;
                    distinctCnt++;
                }

                // If distinct count is equal to k.
                if (distinctCnt == k) ans++;
            }
        }

        return ans;
    }

    public static void main(String[] args) {
        String s = "abc";
        int k = 2;
        System.out.println(countSubstr(s, k));
    }
}
Python
# Python program to find substrings 
# with K Distinct characters

def countSubstr(s, k):
    n = len(s)
    ans = 0

    for i in range(n):

        # Array to check if a character 
        # is present in substring i..j
        map = [False] * 26
        distinctCnt = 0

        for j in range(i, n):

            # If new character is present,
            # increment distinct count.
            if not map[ord(s[j]) - ord('a')]:
                map[ord(s[j]) - ord('a')] = True
                distinctCnt += 1

            # If distinct count is equal to k.
            if distinctCnt == k:
                ans += 1

    return ans

if __name__ == "__main__":
    s = "abc"
    k = 2
    print(countSubstr(s, k))
C#
// C# program to find substrings 
// with K Distinct characters
using System;

class GfG {

    static int countSubstr(string s, int k) {
        int n = s.Length;
        int ans = 0;

        for (int i = 0; i < n; i++) {

            // Array to check if a character 
            // is present in substring i..j
            bool[] map = new bool[26];
            int distinctCnt = 0;

            for (int j = i; j < n; j++) {

                // If new character is present,
                // increment distinct count.
                if (!map[s[j] - 'a']) {
                    map[s[j] - 'a'] = true;
                    distinctCnt++;
                }

                // If distinct count is equal to k.
                if (distinctCnt == k) ans++;
            }
        }

        return ans;
    }

    static void Main() {
        string s = "abc";
        int k = 2;
        Console.WriteLine(countSubstr(s, k));
    }
}
JavaScript
// JavaScript program to find substrings 
// with K Distinct characters

function countSubstr(s, k) {
    let n = s.length;
    let ans = 0;

    for (let i = 0; i < n; i++) {

        // Array to check if a character 
        // is present in substring i..j
        let map = new Array(26).fill(false);
        let distinctCnt = 0;

        for (let j = i; j < n; j++) {

            // If new character is present,
            // increment distinct count.
            if (!map[s.charCodeAt(j) - 'a'.charCodeAt(0)]) {
                map[s.charCodeAt(j) - 'a'.charCodeAt(0)] = true;
                distinctCnt++;
            }

            // If distinct count is equal to k.
            if (distinctCnt === k) ans++;
        }
    }

    return ans;
}

let s = "abc";
let k = 2;
console.log(countSubstr(s, k));

Output
2

[Efficient Approach] Using Sliding Window Method - O(n) time and O(1) space

The idea is to use sliding window technique to efficiently count substrings with at most k distinct characters, and then subtract the count of substrings with at most k-1 distinct characters to obtain the exact number of substrings with exactly k distinct characters.

Step by step approach:

  1. Use a sliding window with an array of size 26 to track character frequencies.
  2. Expand the window to the right, adding characters.
  3. Shrink the window from the left when distinct characters exceed k.
  4. Count all valid substrings within the window.
  5. Subtract substrings with k-1 distinct characters from k distinct characters.
C++
// C++ program to find substrings 
// with K Distinct characters
#include <bits/stdc++.h>
using namespace std;

// Function which finds the number of 
// substrings with atmost k Distinct
// characters.
int count(string &s, int k) {
    int n = s.length();
    int ans = 0;
    
    // Use sliding window technique
    vector<int> freq(26, 0);
    int distinctCnt = 0;
    int i = 0;
    
    for (int j = 0; j < n; j++) {
        
        // Expand window and add character
        freq[s[j] - 'a']++;
        if (freq[s[j] - 'a'] == 1) distinctCnt++;
        
        // Shrink window if distinct characters exceed k
        while (distinctCnt > k) {
            freq[s[i] - 'a']--;
            if (freq[s[i] - 'a'] == 0) distinctCnt--;
            i++;
        }
        
        // Add number of valid substrings ending at j
        ans += j - i + 1;
    }
    
    return ans;
}

// Function to find the number of substrings
// with exactly k Distinct characters.
int countSubstr(string &s, int k) {
    int n = s.length();
    int ans = 0;
    
    // Subtract substrings with at most 
    // k-1 distinct characters from substrings
    // with at most k distinct characters
    ans = count(s, k) - count(s, k-1);
    
    return ans;
}

int main() {
    string s = "abc";
    int k = 2;
    cout << countSubstr(s, k);
    return 0;
}
Java
// Java program to find substrings 
// with K Distinct characters
import java.util.*;

class GfG {

    // Function which finds the number of 
    // substrings with atmost k Distinct
    // characters.
    static int count(String s, int k) {
        int n = s.length();
        int ans = 0;

        // Use sliding window technique
        int[] freq = new int[26];
        int distinctCnt = 0;
        int i = 0;

        for (int j = 0; j < n; j++) {

            // Expand window and add character
            freq[s.charAt(j) - 'a']++;
            if (freq[s.charAt(j) - 'a'] == 1) distinctCnt++;

            // Shrink window if distinct characters exceed k
            while (distinctCnt > k) {
                freq[s.charAt(i) - 'a']--;
                if (freq[s.charAt(i) - 'a'] == 0) distinctCnt--;
                i++;
            }

            // Add number of valid substrings ending at j
            ans += j - i + 1;
        }

        return ans;
    }

    // Function to find the number of substrings
    // with exactly k Distinct characters.
    static int countSubstr(String s, int k) {
        int n = s.length();
        int ans = 0;

        // Subtract substrings with at most 
        // k-1 distinct characters from substrings
        // with at most k distinct characters
        ans = count(s, k) - count(s, k - 1);

        return ans;
    }

    public static void main(String[] args) {
        String s = "abc";
        int k = 2;
        System.out.println(countSubstr(s, k));
    }
}
Python
# Python program to find substrings 
# with K Distinct characters

# Function which finds the number of 
# substrings with atmost k Distinct
# characters.
def count(s, k):
    n = len(s)
    ans = 0

    # Use sliding window technique
    freq = [0] * 26
    distinctCnt = 0
    i = 0

    for j in range(n):

        # Expand window and add character
        freq[ord(s[j]) - ord('a')] += 1
        if freq[ord(s[j]) - ord('a')] == 1:
            distinctCnt += 1

        # Shrink window if distinct characters exceed k
        while distinctCnt > k:
            freq[ord(s[i]) - ord('a')] -= 1
            if freq[ord(s[i]) - ord('a')] == 0:
                distinctCnt -= 1
            i += 1

        # Add number of valid substrings ending at j
        ans += j - i + 1

    return ans

# Function to find the number of substrings
# with exactly k Distinct characters.
def countSubstr(s, k):
    n = len(s)
    ans = 0

    # Subtract substrings with at most 
    # k-1 distinct characters from substrings
    # with at most k distinct characters
    ans = count(s, k) - count(s, k - 1)

    return ans

if __name__ == "__main__":
    s = "abc"
    k = 2
    print(countSubstr(s, k))
C#
// C# program to find substrings 
// with K Distinct characters
using System;

class GfG {

    // Function which finds the number of 
    // substrings with atmost k Distinct
    // characters.
    static int count(string s, int k) {
        int n = s.Length;
        int ans = 0;

        // Use sliding window technique
        int[] freq = new int[26];
        int distinctCnt = 0;
        int i = 0;

        for (int j = 0; j < n; j++) {

            // Expand window and add character
            freq[s[j] - 'a']++;
            if (freq[s[j] - 'a'] == 1) distinctCnt++;

            // Shrink window if distinct characters exceed k
            while (distinctCnt > k) {
                freq[s[i] - 'a']--;
                if (freq[s[i] - 'a'] == 0) distinctCnt--;
                i++;
            }

            // Add number of valid substrings ending at j
            ans += j - i + 1;
        }

        return ans;
    }

    // Function to find the number of substrings
    // with exactly k Distinct characters.
    static int countSubstr(string s, int k) {
        int n = s.Length;
        int ans = 0;

        // Subtract substrings with at most 
        // k-1 distinct characters from substrings
        // with at most k distinct characters
        ans = count(s, k) - count(s, k - 1);

        return ans;
    }

    static void Main() {
        string s = "abc";
        int k = 2;
        Console.WriteLine(countSubstr(s, k));
    }
}
JavaScript
// JavaScript program to find substrings 
// with K Distinct characters

// Function which finds the number of 
// substrings with atmost k Distinct
// characters.
function count(s, k) {
    let n = s.length;
    let ans = 0;

    // Use sliding window technique
    let freq = new Array(26).fill(0);
    let distinctCnt = 0;
    let i = 0;

    for (let j = 0; j < n; j++) {

        // Expand window and add character
        freq[s.charCodeAt(j) - 'a'.charCodeAt(0)]++;
        if (freq[s.charCodeAt(j) - 'a'.charCodeAt(0)] === 1) distinctCnt++;

        // Shrink window if distinct characters exceed k
        while (distinctCnt > k) {
            freq[s.charCodeAt(i) - 'a'.charCodeAt(0)]--;
            if (freq[s.charCodeAt(i) - 'a'.charCodeAt(0)] === 0) distinctCnt--;
            i++;
        }

        // Add number of valid substrings ending at j
        ans += j - i + 1;
    }

    return ans;
}

// Function to find the number of substrings
// with exactly k Distinct characters.
function countSubstr(s, k) {
    let n = s.length;
    let ans = 0;

    // Subtract substrings with at most 
    // k-1 distinct characters from substrings
    // with at most k distinct characters
    ans = count(s, k) - count(s, k - 1);

    return ans;
}

let s = "abc";
let k = 2;
console.log(countSubstr(s, k));

Output
2

Next Article
Article Tags :

Similar Reads