Open In App

Count of substrings of length K with exactly K-1 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 substrings of length k which have exactly k-1 distinct characters.

Example:

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.

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

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

The idea is to consider each substring of length k, and check if it contains exactly k-1 distinct characters.

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

int countOfSubstrings(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 str = "abcc";
	int k = 2;

	cout << countOfSubstrings(str, k) << endl;

	return 0;
}
Java
class GfG {

    static int countOfSubstrings(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 str = "abcc";
        int k = 2;

        System.out.println(countOfSubstrings(str, k));
    }
}
Python
def countOfSubstrings(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

if __name__ == "__main__":
    str = "abcc"
    k = 2

    print(countOfSubstrings(str, k))
C#
using System;

class GfG {

    static int countOfSubstrings(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 str = "abcc";
        int k = 2;

        Console.WriteLine(countOfSubstrings(str, k));
    }
}
JavaScript
function countOfSubstrings(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;
}

let str = "abcc";
let k = 2;

console.log(countOfSubstrings(str, k));

Output
1

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

The idea is to use a sliding window of length k across the string and count how many windows contain exactly k-1 distinct characters. We maintain a frequency counter for each character in the current window and check if the number of distinct characters (characters with non-zero frequency) is equal to k-1.

Step by step approach:

  1. Initialize a frequency array to track the count of each lowercase character in the current window.
  2. Build the initial window of size k-1, then slide through the string one character at a time.
  3. For each window position, add the new character and check if exactly k-1 distinct characters exist. If the condition is met, increment the result counter.
  4. Before sliding the window, remove the leftmost character from the frequency count.
C++
#include <bits/stdc++.h>
using namespace std;
int countOfSubstrings(string &s, int k) {
    
    // If k is greater than string length 
    if (k > s.length()) return 0;
    
	int n = s.length(), j = 0;
	vector<int> cnt(26, 0);
	int ans = 0;
	
	for (int i=0; i<k-1; i++) {
	    cnt[s[i]-'a']++;
	}

	for (int i=k-1; i<n; i++) {
	   
	    cnt[s[i]-'a']++;
	    
	    // Check if the current window
	    // contains k-1 distinct chars. 
	    int distinctCnt = 0;
	    for (int j=0; j<26; j++) {
	        if (cnt[j] > 0) distinctCnt++;
	    }
	    if (distinctCnt == k-1) ans++;
	    
	    cnt[s[i-k+1]-'a']--;
	}
	
	return ans;
}

int main() {

	string str = "abcc";
	int k = 2;

	cout << countOfSubstrings(str, k) << endl;

	return 0;
}
Java
class GfG {

    static int countOfSubstrings(String s, int k) {
        
         
        if (k > s.length()) return 0;
        
        int n = s.length();
        int[] cnt = new int[26];
        int ans = 0;
        
        for (int i = 0; i < k - 1; i++) {
            cnt[s.charAt(i) - 'a']++;
        }

        for (int i = k - 1; i < n; i++) {
            
            
            cnt[s.charAt(i) - 'a']++;
            
            // Check if the current window
            // contains k-1 distinct chars. 
            int distinctCnt = 0;
            for (int j1 = 0; j1 < 26; j1++) {
                if (cnt[j1] > 0) distinctCnt++;
            }
            if (distinctCnt == k - 1) ans++;
            
            cnt[s.charAt(i - k + 1) - 'a']--;
        }
        
        return ans;
    }

    public static void main(String[] args) {

        String str = "abcc";
        int k = 2;

        System.out.println(countOfSubstrings(str, k));
    }
}
Python
def countOfSubstrings(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__":
    str = "abcc"
    k = 2

    print(countOfSubstrings(str, k))
C#
using System;

class GfG {

    static int countOfSubstrings(string s, int k) {
        
        if (k > s.Length) return 0;
        
        int n = s.Length;
        int[] cnt = new int[26];
        int ans = 0;
        
        for (int i = 0; i < k - 1; i++) {
            cnt[s[i] - 'a']++;
        }

        for (int i = k - 1; i < n; i++) {
            
            cnt[s[i] - 'a']++;
            
            // Check if the current window
            // contains k-1 distinct chars. 
            int distinctCnt = 0;
            for (int j1 = 0; j1 < 26; j1++) {
                if (cnt[j1] > 0) distinctCnt++;
            }
            if (distinctCnt == k - 1) ans++;

            cnt[s[i - k + 1] - 'a']--;
        }
        
        return ans;
    }

    static void Main() {

        string str = "abcc";
        int k = 2;

        Console.WriteLine(countOfSubstrings(str, k));
    }
}
JavaScript
function countOfSubstrings(s, k) {
    
    // If k is greater than string length 
    if (k > s.length) return 0;
    
    let n = s.length;
    let cnt = new Array(26).fill(0);
    let ans = 0;
    
    for (let i = 0; i < k - 1; i++) {
        cnt[s.charCodeAt(i) - 'a'.charCodeAt(0)]++;
    }

    for (let i = k - 1; i < n; i++) {
        
        cnt[s.charCodeAt(i) - 'a'.charCodeAt(0)]++;
        
        // Check if the current window
        // contains k-1 distinct chars.
        let distinctCnt = cnt.filter(x => x > 0).length;
        if (distinctCnt === k - 1) ans++;
        
        cnt[s.charCodeAt(i - k + 1) - 'a'.charCodeAt(0)]--;
    }

    return ans;
}

let str = "abcc";
let k = 2;

console.log(countOfSubstrings(str, k));

Output
1

Next Article

Similar Reads