Open In App

Count odd length Substrings with median same as Kth character of String

Given a string S of size N, the task is to find the number of substrings of odd lengths that have a median equal to the Kth character of the string.

Examples:



Input: S = “ecadgg”, K = 4
Output: 4
Explanation: Character at 4th position in string is ‘d’. 
Then there are 4 odd length substrings with ‘d’ as their median: 
[d], [a, d, g], [e, c, a, d, g], therefore return 4 as the answer.

Input: s = “abc”, K = 1
Output: 1
Explanation: Character at 1st position in string is ‘a’. Then there is only 1 odd length substring with ‘a’ as its median: [a] therefore return 1 as the answer.



Approach: To solve the problem follow the below idea:

Median is middle element. So smaller elements has to be equal to number of bigger elements, the desired substrings would be like (S[K]) or (2 elements on left and right), (4 elements on left and right), so on. . . [cannot take 1, 3 . . . because the substring should have odd length]

  • We can maintain smaller and bigger arrays of length N and populate them.
  • This helps us to find in range [i, j] count of smaller and bigger elements with respect to S[K]. 
    • For S[K] to be median in the range [i, j], the number of characters smaller than S[K] should be equal to the number of characters greater than S[K] and the subarray should include S[K].

Note: We are considering 1based indexing of string for understanding but the actual implementation uses 0 based indexing.

Follow the steps to solve the problem:

Below is the implementation of the above approach.




// C++ code to implement the approach
 
#include <bits/stdc++.h>
using namespace std;
 
// Function for finding the number of
// sub strings in (start, end) where
// sum of difference is zero
int sum(int start, int end, vector<int>& v)
{
    // STL map to store number of subarrays
    // starting from index zero having
    // particular value of sum.
    unordered_map<int, int> prevSum;
 
    int res = 0, currSum = 0;
 
    for (int i = start; i < end; i++) {
 
        // Add current element to sum so far.
        currSum += v[i];
 
        // If currsum is equal to 0, then
        // a new subarray is found.
        // So increase count of subarrays.
        if (currSum == 0)
            res++;
 
        if (prevSum.find(currSum) != prevSum.end())
            res += (prevSum[currSum]);
 
        // Add currsum value to count of
        // different values of sum.
        prevSum[currSum]++;
    }
 
    return res;
}
 
// Function to find odd length substrings
// whose median is equal to s[k-1]
int numberOfSubstrings(string& s, int k)
{
    int n = s.size();
 
    // Initializing vectors for storing
    // element is smaller or greater
    // than median
    vector<int> smaller(n, 0), greater(n, 0);
    for (int i = 0; i < n; i++) {
        smaller[i] = s[i] < s[k - 1];
 
        greater[i] = s[i] > s[k - 1];
    }
 
    // Declaring a vector to store
    // difference of greater and smaller
    // characters for each position
    vector<int> diff(n, 0);
    for (int i = 0; i < n; i++)
        diff[i] = smaller[i] - greater[i];
 
    // Substrings in (0 to n)
    int val1 = sum(0, n, diff);
 
    // Substrings  in (0 to k-1)
    int val2 = sum(0, k - 1, diff);
 
    // Substrings in (k to n)
    int val3 = sum(k, n, diff);
 
    // Considering only those sub strings
    // with difference 0 that
    // contains s[k-1]
    return val1 - val2 - val3;
}
 
// Driver code
int main()
{
    string S = "ecadgg";
    int K = 4;
 
    // Function call
    cout << numberOfSubstrings(S, K);
 
    return 0;
}




// Java code to implement the approach
import java.io.*;
import java.util.*;
 
class GFG {
    // Function for finding the number of
    // sub strings in (start, end) where
    // sum of difference is zero
    public static int sum(int start, int end, int v[])
    {
        // STL map to store number of subarrays
        // starting from index zero having
        // particular value of sum.
        HashMap<Integer, Integer> prevSum
            = new HashMap<Integer, Integer>();
 
        int res = 0, currSum = 0;
 
        for (int i = start; i < end; i++) {
 
            // Add current element to sum so far.
            currSum += v[i];
 
            // If currsum is equal to 0, then
            // a new subarray is found.
            // So increase count of subarrays.
            if (currSum == 0)
                res++;
 
            if (prevSum.containsKey(currSum)) {
                res += prevSum.get(currSum);
                prevSum.put(currSum,
                            prevSum.get(currSum) + 1);
            }
            // Add currsum value to count of
            // different values of sum.
            prevSum.put(currSum, 1);
        }
 
        return res;
    }
 
    // Function to find odd length substrings
    // whose median is equal to s[k-1]
    public static int numberOfSubstrings(String s, int k)
    {
        int n = s.length();
 
        // Initializing vectors for storing
        // element is smaller or greater
        // than median
        int smaller[] = new int[n];
        int greater[] = new int[n];
        for (int i = 0; i < n; i++) {
            smaller[i]
                = (s.charAt(i) < s.charAt(k - 1)) ? 1 : 0;
 
            greater[i]
                = (s.charAt(i) > s.charAt(k - 1)) ? 1 : 0;
        }
 
        // Declaring a vector to store
        // difference of greater and smaller
        // characters for each position
        int diff[] = new int[n];
        for (int i = 0; i < n; i++)
            diff[i] = smaller[i] - greater[i];
 
        // Substrings in (0 to n)
        int val1 = sum(0, n, diff);
 
        // Substrings  in (0 to k-1)
        int val2 = sum(0, k - 1, diff);
 
        // Substrings in (k to n)
        int val3 = sum(k, n, diff);
 
        // Considering only those sub strings
        // with difference 0 that
        // contains s[k-1]
        return val1 - val2 - val3;
    }
 
    // Driver Code
    public static void main(String[] args)
    {
        String S = "ecadgg";
        int K = 4;
 
        // Function call
        System.out.print(numberOfSubstrings(S, K));
    }
}
 
// This code is contributed by Rohit Pradhan




# Python code for the above approach
 
# Function for finding the number of
# sub strings in (start, end) where
# sum of difference is zero
def sum(start, end, v):
   
    # STL map to store number of subarrays
    # starting from index zero having
    # particular value of sum.
    prevSum = {};
 
    res = 0
    currSum = 0;
 
    for i in range(start, end):
 
        # Add current element to sum so far.
        currSum += v[i];
 
        # If currsum is equal to 0, then
        # a new subarray is found.
        # So increase count of subarrays.
        if (currSum == 0):
            res += 1
 
        if (currSum in prevSum):
            res += (prevSum[currSum]);
 
 
        # Add currsum value to count of
        # different values of sum.
        if (currSum in prevSum):
            prevSum[currSum] += 1
        else:
            prevSum[currSum] = 1
    return res;
 
# Function to find odd length substrings
# whose median is equal to s[k-1]
def numberOfSubstrings(s, k):
    n = len(s)
 
    # Initializing vectors for storing
    # element is smaller or greater
    # than median
    smaller = [0] * n
    greater = [0] * n
    for i in range(n):
        smaller[i] = s[i] < s[k - 1];
 
        greater[i] = s[i] > s[k - 1];
     
 
    # Declaring a vector to store
    # difference of greater and smaller
    # characters for each position
    diff = [0] * n
    for i in range(n):
        diff[i] = smaller[i] - greater[i];
 
    # Substrings in (0 to n)
    val1 = sum(0, n, diff);
 
    # Substrings  in (0 to k-1)
    val2 = sum(0, k - 1, diff);
 
    # Substrings in (k to n)
    val3 = sum(k, n, diff);
 
    # Considering only those sub strings
    # with difference 0 that
    # contains s[k-1]
    return val1 - val2 - val3;
 
# Driver code
S = "ecadgg";
K = 4;
 
# Function call
print(numberOfSubstrings(S, K));
 
 # This code is contributed by Saurabh Jaiswal
 
    




// C# code for the above approach
 
using System;
using System.Collections;
using System.Collections.Generic;
 
public class GFG {
 
    // Function for finding the number of
    // sub strings in (start, end) where
    // sum of difference is zero
    public static int sum(int start, int end, int[] v)
    {
        // Dictionary to store number of subarrays
        // starting from index zero having
        // particular value of sum.
        Dictionary<int, int> prevSum
            = new Dictionary<int, int>();
 
        int res = 0, currSum = 0;
 
        for (int i = start; i < end; i++) {
 
            // Add current element to sum so far.
            currSum += v[i];
 
            // If currsum is equal to 0, then
            // a new subarray is found.
            // So increase count of subarrays.
            if (currSum == 0)
                res++;
 
            if (prevSum.ContainsKey(currSum)) {
                res += prevSum[currSum];
                prevSum[currSum] += 1;
            }
            // Add currsum value to count of
            // different values of sum.
            else {
                prevSum.Add(currSum, 1);
            }
        }
 
        return res;
    }
 
    // Function to find odd length substrings
    // whose median is equal to s[k-1]
    public static int numberOfSubstrings(String s, int k)
    {
        int n = s.Length;
 
        // Initializing vectors for storing
        // element is smaller or greater
        // than median
        int[] smaller = new int[n];
        int[] greater = new int[n];
        for (int i = 0; i < n; i++) {
            smaller[i] = (s[i] < s[k - 1]) ? 1 : 0;
            greater[i] = (s[i] > s[k - 1]) ? 1 : 0;
        }
 
        // Declaring a vector to store
        // difference of greater and smaller
        // characters for each position
        int[] diff = new int[n];
        for (int i = 0; i < n; i++)
            diff[i] = smaller[i] - greater[i];
 
        // Substrings in (0 to n)
        int val1 = sum(0, n, diff);
 
        // Substrings  in (0 to k-1)
        int val2 = sum(0, k - 1, diff);
 
        // Substrings in (k to n)
        int val3 = sum(k, n, diff);
 
        // Considering only those sub strings
        // with difference 0 that
        // contains s[k-1]
        return val1 - val2 - val3;
    }
 
    static public void Main()
    {
 
        // Code
        String S = "ecadgg";
        int K = 4;
 
        // Function call
        Console.Write(numberOfSubstrings(S, K));
    }
}
 
// This code is contributed by lokeshmvs21.




   <script>
       // JavaScript code for the above approach
 
       // Function for finding the number of
       // sub strings in (start, end) where
       // sum of difference is zero
 
       function sum(start, end, v) {
           // STL map to store number of subarrays
           // starting from index zero having
           // particular value of sum.
           let prevSum = new Map();
 
           let res = 0, currSum = 0;
 
           for (let i = start; i < end; i++) {
 
               // Add current element to sum so far.
               currSum += v[i];
 
               // If currsum is equal to 0, then
               // a new subarray is found.
               // So increase count of subarrays.
               if (currSum == 0)
                   res++;
 
               if (prevSum.has(currSum))
                   res += (prevSum.get(currSum));
 
 
               // Add currsum value to count of
               // different values of sum.
 
               if (prevSum.has(currSum))
                   prevSum.set(currSum, prevSum.get(currSum) + 1);
               else
                   prevSum.set(currSum, 1);
           }
 
           return res;
       }
 
       // Function to find odd length substrings
       // whose median is equal to s[k-1]
       function numberOfSubstrings(s, k) {
           let n = s.length;
 
           // Initializing vectors for storing
           // element is smaller or greater
           // than median
           let smaller = new Array(n).fill(0), greater = new Array(n).fill(0);
           for (let i = 0; i < n; i++) {
               smaller[i] = s[i] < s[k - 1];
 
               greater[i] = s[i] > s[k - 1];
           }
 
           // Declaring a vector to store
           // difference of greater and smaller
           // characters for each position
           let diff = new Array(n).fill(0);
           for (let i = 0; i < n; i++)
               diff[i] = smaller[i] - greater[i];
 
           // Substrings in (0 to n)
           let val1 = sum(0, n, diff);
 
           // Substrings  in (0 to k-1)
           let val2 = sum(0, k - 1, diff);
 
           // Substrings in (k to n)
           let val3 = sum(k, n, diff);
 
           // Considering only those sub strings
           // with difference 0 that
           // contains s[k-1]
           return val1 - val2 - val3;
       }
 
       // Driver code
       let S = "ecadgg";
       let K = 4;
 
       // Function call
       document.write(numberOfSubstrings(S, K));
 
// This code is contributed by Potta Lokesh
 
   </script>

Output
4

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


Article Tags :