Open In App

Count of substrings of length K with exactly K-1 distinct characters

Last Updated : 01 Jul, 2025
Summarize
Comments
Improve
Suggest changes
Share
Like Article
Like
Report

Given a string s consisting of lowercase characters and an integer k, find the count of all substrings of length k which have exactly k-1 distinct characters.

Example:

Input: s = "aabab", k = 3 
Output: 3
Explanation: Substrings of length 3 are "aab", "aba", "bab". All 3 substrings contains 2 distinct characters.

Input: s = "abcc", k = 2 
Output: 1
Explanation: Substrings of length 2 are "ab", "bc" and "cc". Only "cc" has 2-1 = 1 distinct character.

[Naive Approach] Checking each substring- O(n * k) time and O(1) space

The main idea of this approach is to iterate through all possible substrings of length k in the given string s. For each substring, it uses a frequency array to count the occurrences of each character. Then, it calculates how many distinct characters are present in that substring. If the number of distinct characters equals k - 1, the substring satisfies the condition and the count is incremented.

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

int substrCount(string &s, int k) {

	int n = s.length();
	int count = 0;

	// Check for all subarray of size K
	for (int i = 0; i < n - k + 1; i++) {
		vector<int> cnt(26, 0);

		for (int j=i; j<i+k; j++)
			cnt[s[j] - 'a']++;
			
		int distinctCnt = 0;

		// Count number of distinct characters
		for (int i=0; i<26; i++) {
		    if (cnt[i] > 0) {
		        distinctCnt++;
		    }
		}
		
		if (distinctCnt == k-1) count++;
	}

	return count;
}

int main() {

	string s = "aabab";
	int k =3;
	cout << substrCount(s, k) << endl;

	return 0;
}
Java
class GfG {

    static int substrCount(String s, int k) {

        int n = s.length();
        int count = 0;

        // Check for all subarray of size K
        for (int i = 0; i < n - k + 1; i++) {
            int[] cnt = new int[26];

            for (int j = i; j < i + k; j++)
                cnt[s.charAt(j) - 'a']++;

            int distinctCnt = 0;

            // Count number of distinct characters
            for (int i1 = 0; i1 < 26; i1++) {
                if (cnt[i1] > 0) {
                    distinctCnt++;
                }
            }

            if (distinctCnt == k - 1) count++;
        }

        return count;
    }

    public static void main(String[] args) {

        String s = "aabab";
        int k = 3;
        System.out.println(substrCount(s, k));
    }
}
Python
def substrCount(s, k):
    n = len(s)
    count = 0

    # Check for all subarray of size K
    for i in range(n - k + 1):
        cnt = [0] * 26

        for j in range(i, i + k):
            cnt[ord(s[j]) - ord('a')] += 1

        distinctCnt = sum(1 for x in cnt if x > 0)

        if distinctCnt == k - 1:
            count += 1

    return count

# Driver Code
if __name__ == "__main__":
    s = "aabab"
    k = 3
    print(substrCount(s, k))
C#
using System;

class GfG {

    static int substrCount(string s, int k) {

        int n = s.Length;
        int count = 0;

        // Check for all subarray of size K
        for (int i = 0; i < n - k + 1; i++) {
            int[] cnt = new int[26];

            for (int j = i; j < i + k; j++)
                cnt[s[j] - 'a']++;

            int distinctCnt = 0;

            // Count number of distinct characters
            for (int i1 = 0; i1 < 26; i1++) {
                if (cnt[i1] > 0) {
                    distinctCnt++;
                }
            }

            if (distinctCnt == k - 1) count++;
        }

        return count;
    }

    public static void Main(string[] args) {

        string s = "aabab";
        int k = 3;
        Console.WriteLine(substrCount(s, k));
    }
}
JavaScript
function substrCount(s, k) {
    let n = s.length;
    let count = 0;

    // Check for all subarray of size K
    for (let i = 0; i < n - k + 1; i++) {
        let cnt = new Array(26).fill(0);

        for (let j = i; j < i + k; j++)
            cnt[s.charCodeAt(j) - 'a'.charCodeAt(0)]++;

        let distinctCnt = cnt.filter(x => x > 0).length;

        if (distinctCnt === k - 1) count++;
    }

    return count;
}

// Dricer Code
let s = "aabab";
let k = 3;
console.log(substrCount(s, k));

Output
3

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

The idea is to maintains a 26 element frequency array for letters a–z and a counter distinctCnt for how many different letters are currently in the window. First, it preloads the initial k - 1 characters so that each subsequent step merely adds one new character (expanding the window to size k), checks whether the window now contains exactly k - 1 distinct letters, and, if so, increments the answer. Then it removes the leftmost character to keep the window size constant before moving to the next index.

Illustration:

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

int substrCount(string &s, int k) {
    
    // Return 0 if window size k is greater than the string length
    if (k > s.length()) return 0;
    
    int n = s.length();
    
    // Frequency array for characters a-z
    vector<int> cnt(26, 0);  
    int ans = 0;
    int distinctCnt = 0;

    // Preprocess the first k-1 characters
    for (int i = 0; i < k - 1; i++) {
        cnt[s[i] - 'a']++;
        
        if (cnt[s[i] - 'a'] == 1) distinctCnt++; 
    }

    // Start sliding window
    for (int i = k - 1; i < n; i++) {
        cnt[s[i] - 'a']++;
        if (cnt[s[i] - 'a'] == 1) distinctCnt++;  

        // Check if window has exactly k-1 distinct characters
        if (distinctCnt == k - 1) ans++;

        // Remove the character going out of the window
        cnt[s[i - k + 1] - 'a']--;
        
        if (cnt[s[i - k + 1] - 'a'] == 0) distinctCnt--;  
    }

    return ans;
}

int main() {
    
    string str = "aabab";
    int k = 3;
    cout << substrCount(str, k) << endl;

    return 0;
}
Java
import java.util.*;

class GfG {

    static int substrCount(String s, int k) {

        // If k is larger than the string length, return 0
        if (k > s.length()) return 0;

        int n = s.length();
        
        // Frequency array for characters 'a' to 'z'
        int[] cnt = new int[26]; 
        int ans = 0;
        int distinctCnt = 0;

        // Pre-fill the first (k-1) characters in frequency array
        for (int i = 0; i < k - 1; i++) {
            int index = s.charAt(i) - 'a';
            cnt[index]++;
            
            // New distinct character
            if (cnt[index] == 1) distinctCnt++; 
        }

        // Start sliding window of size k
        for (int i = k - 1; i < n; i++) {
            int addIndex = s.charAt(i) - 'a';
            cnt[addIndex]++;
            
            // New distinct character added
            if (cnt[addIndex] == 1) distinctCnt++; 

            // If exactly (k - 1) distinct characters, it's valid
            if (distinctCnt == k - 1) ans++;

            // Remove the character going out from the left of window
            int removeIndex = s.charAt(i - k + 1) - 'a';
            cnt[removeIndex]--;
            
            // One distinct character removed
            if (cnt[removeIndex] == 0) distinctCnt--; 
        }

        return ans;
    }

    public static void main(String[] args) {
        
        String s = "aabab";
        int k = 3;
        System.out.println(substrCount(s, k));
    }
}
Python
def substrCount(s, k):
    
    if k > len(s):
        return 0

    n = len(s)
    cnt = [0] * 26
    ans = 0

    for i in range(k - 1):
        cnt[ord(s[i]) - ord('a')] += 1

    for i in range(k - 1, n):
        
        cnt[ord(s[i]) - ord('a')] += 1

        # Check if the current window
        # contains k-1 distinct chars.
        distinctCnt = sum(1 for x in cnt if x > 0)
        if distinctCnt == k - 1:
            ans += 1

        cnt[ord(s[i - k + 1]) - ord('a')] -= 1

    return ans

if __name__ == "__main__":
    s = "aabab"
    k = 3
    print(substrCount(s, k))
C#
using System;

class GfG{
    
    static int substrCount(string s, int k){
        
        // If k is greater than string length, return 0
        if (k > s.Length) return 0;

        int n = s.Length;
        
        // Frequency array for a-z
        int[] cnt = new int[26]; 
        int ans = 0;
        int distinctCnt = 0;

        // Preprocess first (k - 1) characters
        for (int i = 0; i < k - 1; i++){
            
            int index = s[i] - 'a';
            cnt[index]++;
            if (cnt[index] == 1) distinctCnt++; 
        }

        // Slide the window across the string
        for (int i = k - 1; i < n; i++){
            
            int addIndex = s[i] - 'a';
            cnt[addIndex]++;
            if (cnt[addIndex] == 1) distinctCnt++; 

            // Check if window has exactly k - 1 distinct characters
            if (distinctCnt == k - 1) ans++;

            // Remove character from the left of the window
            int removeIndex = s[i - k + 1] - 'a';
            cnt[removeIndex]--;
            
            if (cnt[removeIndex] == 0) distinctCnt--; 
        }

        return ans;
    }

    static void Main(){
        
        string s = "aabab";
        int k = 3;
        Console.WriteLine(substrCount(s, k)); 
    }
}
JavaScript
function substrCount(s, k) {

  // Edge case: window larger than string
  if (k > s.length) return 0;

  const n = s.length;
  
  // frequency array for 'a' … 'z'
  const cnt = new Array(26).fill(0);  
  let ans = 0;
  let distinctCnt = 0;

  // Preload first k-1 characters
  for (let i = 0; i < k - 1; i++) {
    const idx = s.charCodeAt(i) - 97;
    
    // new distinct char
    if (++cnt[idx] === 1) distinctCnt++; 
  }

  // Slide window of exact size k
  for (let i = k - 1; i < n; i++) {
    const addIdx = s.charCodeAt(i) - 97;
    if (++cnt[addIdx] === 1) distinctCnt++;   

    if (distinctCnt === k - 1) ans++;         

    const remIdx = s.charCodeAt(i - k + 1) - 97;
    if (--cnt[remIdx] === 0) distinctCnt--;   
  }

  return ans;
}

// Driver Code
let s = "aabab";
let k = 3;
console.log(substrCount(s, k)); 

Output
3

Article Tags :
Practice Tags :

Similar Reads