Open In App

Count Substrings with all Unique Digits in Range [0, K]

Last Updated : 23 Dec, 2023
Improve
Improve
Like Article
Like
Save
Share
Report

Given a string S of length N (1 <= N <= 107) and a positive integer K, where the string contains only numbers in the range [0, 9], the task is to determine the count of substrings that include at least one occurrence of all the unique digits within the specified range [0, K].

Example:

Input: S = “4250163456”, K = 3
Output: 5
Explanation: The substrings containing at least one occurrence of all first three unique digits in the range [0, 3] are “4250163“, “42501634“, “425016345″, “4250163456″, “250163“, “250163“, “2501634″, “25016345″, “250163456″.

Input: S = “978623”, K = 5
Output: 0

Count Substrings with All Unique Digits in Range [0, K] using Hashing:

Begin with two pointers, start and end, both at the string’s beginning. For each start, find the first valid substring starting at start and ending at end. Since this is the first valid substring from start, we can also include the remaining characters from the end index, meeting the minimum validity criteria. There will be (N – end) valid substrings for this start index. Add up all these counts to the result and return it.

Step-by-step approach:

  • Create a character frequency map unmap and variables start, end, n (string size), and result to 0.
  • Create through the string s until the end is less than its size n.
  • If the character at end is in the range [0, K], increment its frequency count in unmap.
  • Check if unmap contains K+1 unique characters. If it does, initiate a loop until unmap contains K unique characters:
    • Increment result by the count of valid substrings, which is (n – end).
    • Decrement the frequency count of the character at start if it’s in the range [0, K].
    • If the frequency count becomes 0, remove that character from unmap.
    • Increment start.
  • Increment end and continue.
  • Return result as the final count of valid substrings.

Below is the implementation of the above approach.

C++




// C++ code to implement the approach
 
#include <bits/stdc++.h>
using namespace std;
 
// Function to find the number of substrings
int countSubstrings(string s, int K)
{
    // Initilize a map for keeping
    // frequency of characters
    unordered_map<char, int> unmap;
 
    // Initilize a variable start = 0,
    // end = 0 and result = 0
    int start = 0, end = 0, n = s.size(), result = 0;
 
    // Do while end is less than size
    // of given string
    while (end < n) {
 
        // Increment the frequency of
        // character at end, if is lies in
        // the range [0, K].
        if (s[end] <= (K + '0'))
            unmap[s[end]]++;
 
        // Check if the size of
        // map becomes K
        if (unmap.size() == K + 1) {
 
            // Initiate a while loop
            // unless map size is
            // equals to K
            while (unmap.size() == K + 1) {
 
                // Increment the value of
                // result by n - end, because
                // (n - end) substring are valid
                // that satisfy the given
                // condition
                result += n - end;
 
                // Decrement the frequency
                // count of character at
                // start, if it participate
                // previously in map
                if (s[start] <= (K + '0'))
                    unmap[s[start]]--;
 
                // Check if frequency count
                // of character at start in
                // map becomes 0.
                // If true, then remove this
                // character from the map
                if (unmap[s[start]] == 0)
                    unmap.erase(s[start]);
 
                // Move the start pointer
                // to right by incrementing
                // its value by 1
                start++;
            }
 
            // Increment the end pointer.
            end++;
        }
 
        // Otherwise, Increment
        // the end pointer by 1.
        else {
            end++;
        }
    }
 
    // Return the value of result
    return result;
}
 
// Driver code
int main()
{
    string S = "4250163456";
    int K = 3;
 
    // Function Call
    cout << countSubstrings(S, K);
 
    return 0;
}


Java




import java.util.HashMap;
import java.util.Map;
 
public class SubstringCount {
 
    // Function to find the number of substrings
    static int countSubstrings(String s, int K)
    {
        // Initialize a map for keeping frequency of
        // characters
        Map<Character, Integer> map = new HashMap<>();
 
        // Initialize variables start = 0, end = 0, and
        // result = 0
        int start = 0, end = 0, n = s.length(), result = 0;
 
        // Iterate while end is less than the size of the
        // given string
        while (end < n) {
            // Increment the frequency of the character at
            // end if it is less than or equal to K
            if (s.charAt(end) <= (K + '0')) {
                map.put(s.charAt(end),
                        map.getOrDefault(s.charAt(end), 0)
                            + 1);
            }
 
            // Check if the size of the map becomes K + 1
            if (map.size() == K + 1) {
                // Initiate a while loop unless map size is
                // equal to K
                while (map.size() == K + 1) {
                    // Increment the value of result by (n -
                    // end) because (n - end) substrings are
                    // valid that satisfy the given
                    // condition
                    result += n - end;
 
                    // Decrement the frequency count of the
                    // character at start if it participated
                    // previously in the map
                    if (s.charAt(start) <= (K + '0')) {
                        map.put(s.charAt(start),
                                map.get(s.charAt(start))
                                    - 1);
                        if (map.get(s.charAt(start)) == 0) {
                            map.remove(s.charAt(start));
                        }
                    }
 
                    // Move the start pointer to the right
                    // by incrementing its value by 1
                    start++;
                }
 
                // Increment the end pointer
                end++;
            }
            else {
                // Increment the end pointer by 1
                end++;
            }
        }
 
        // Return the value of result
        return result;
    }
 
    // Driver code
    public static void main(String[] args)
    {
        String S = "4250163456";
        int K = 3;
 
        // Function Call
        System.out.println(countSubstrings(S, K));
    }
}


Python3




# Python code to implement the approach
def countSubstrings(s, K):
    # Initialize a dictionary to keep
    # frequency of characters
    unmap = {}
 
    # Initialize variables: start = 0,
    # end = 0, and result = 0
    start, end, n, result = 0, 0, len(s), 0
 
    # Loop until end is less than the
    # size of the given string
    while end < n:
        # Increment the frequency of character
        # at end if it's in the range [0, K]
        if s[end] <= chr(K + ord('0')):
            unmap[s[end]] = unmap.get(s[end], 0) + 1
 
        # Check if the size of the map becomes K + 1
        if len(unmap) == K + 1:
            # While loop until map size is equal to K
            while len(unmap) == K + 1:
                # Increment the value of result by
                # n - end because (n - end) substrings
                # are valid satisfying the condition
                result += n - end
 
                # Decrement the frequency count of
                # character at start if it's
                # in the range [0, K]
                if s[start] <= chr(K + ord('0')):
                    unmap[s[start]] = unmap.get(s[start], 0) - 1
 
                    # If frequency count becomes 0,
                    # remove the character from the map
                    if unmap[s[start]] == 0:
                        del unmap[s[start]]
 
                # Move the start pointer to the
                # right by incrementing its value by 1
                start += 1
 
            # Increment the end pointer
            end += 1
 
        # Otherwise, increment the end
        # pointer by 1
        else:
            end += 1
 
    # Return the value of result
    return result
 
 
# Driver code
S = "4250163456"
K = 3
 
# Function Call
print(countSubstrings(S, K))


C#




using System;
using System.Collections.Generic;
 
public class SubstringCount {
    // Function to find the number of substrings
    static int CountSubstrings(string s, int K)
    {
        // Initialize a dictionary for keeping frequency of
        // characters
        Dictionary<char, int> map
            = new Dictionary<char, int>();
 
        // Initialize variables start = 0, end = 0, and
        // result = 0
        int start = 0, end = 0, n = s.Length, result = 0;
 
        // Iterate while end is less than the size of the
        // given string
        while (end < n) {
            // Increment the frequency of the character at
            // end if it is less than or equal to K
            if (s[end] <= (K + '0')) {
                map[s[end]]
                    = map.GetValueOrDefault(s[end], 0) + 1;
            }
 
            // Check if the size of the map becomes K + 1
            if (map.Count == K + 1) {
                // Initiate a while loop unless map size is
                // equal to K
                while (map.Count == K + 1) {
                    // Increment the value of result by (n -
                    // end) because (n - end) substrings are
                    // valid that satisfy the given
                    // condition
                    result += n - end;
 
                    // Decrement the frequency count of the
                    // character at start if it participated
                    // previously in the map
                    if (s[start] <= (K + '0')) {
                        map[s[start]] = map[s[start]] - 1;
                        if (map[s[start]] == 0) {
                            map.Remove(s[start]);
                        }
                    }
 
                    // Move the start pointer to the right
                    // by incrementing its value by 1
                    start++;
                }
 
                // Increment the end pointer
                end++;
            }
            else {
                // Increment the end pointer by 1
                end++;
            }
        }
 
        // Return the value of result
        return result;
    }
 
    // Driver code
    public static void Main(string[] args)
    {
        string S = "4250163456";
        int K = 3;
 
        // Function Call
        Console.WriteLine(CountSubstrings(S, K));
    }
}


Javascript




function GFG(s, K) {
    // Initialize a map for keeping frequency of the characters
    const unmap = new Map();
    let start = 0,
        end = 0,
        n = s.length,
        result = 0;
    // Do while end is less than the size of the given string
    while (end < n) {
        if (s[end] <= String(K)) {
            unmap.set(s[end], (unmap.get(s[end]) || 0) + 1);
        }
        // Check if the size of the map becomes K + 1
        if (unmap.size === K + 1) {
            // Initiate a while loop unless map size is equal to K
            while (unmap.size === K + 1) {
                // Increment the value of result by n - end,
                // because (n - end) substrings are valid that
                result += n - end;
                // Decrement the frequency count of the character at start if it participated
                if (s[start] <= String(K)) {
                    unmap.set(s[start], unmap.get(s[start]) - 1);
                }
                // Check if the frequency count of the
                // character at start in the map becomes 0
                if (unmap.get(s[start]) === 0) {
                    unmap.delete(s[start]);
                }
                start++;
            }
            // Increment the end pointer
            end++;
        } else {
            // Otherwise, increment the end pointer by 1
            end++;
        }
    }
    // Return the value of result
    return result;
}
// Driver code
const S = "4250163456";
const K = 3;
console.log(GFG(S, K));


Output

8









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



Like Article
Suggest improvement
Share your thoughts in the comments

Similar Reads