Skip to content
Related Articles
Open in App
Not now

Related Articles

Number of substrings having an equal number of lowercase and uppercase letters

Improve Article
Save Article
Like Article
  • Difficulty Level : Hard
  • Last Updated : 30 Sep, 2022
Improve Article
Save Article
Like Article

Given string S consists of lowercase and uppercase letters, the task is to find the number of substrings having an equal number of lowercase and uppercase letters.

Examples:

Input: S = “gEEk”
Output: 3
Explanation:
The following are the substrings having an equal number of lowercase and uppercase letters:

  1. “gE”
  2. “gEEk”
  3. “Ek”

Therefore, the total count of substrings is 3.

Input: S = “WomensDAY”
Output: 4

Naive Approach: The simplest approach to solve the given problem is to generate all possible substring of the given string S and increment the count of a substring by 1 if that substring contains an equal number of lowercase and uppercase letters. After checking for all the substrings, print the value of the count as the result. 

Time Complexity: O(N3)
Auxiliary Space: O(1)

Efficient Approach: The given problem can be solved by considering each lowercase and uppercase letter as 1 and -1 respectively, and then find the count of subarray having sum 0. Follow the steps to solve the problem:

  • Initialize a HashMap, say M that stores the frequency of the sum of all the prefixes.
  • Initialize a variable, say, currentSum as 0 and res as 0 that stores the sum of each prefix and count of the resultant substrings respectively.
  • Traverse the string and perform the following steps:
    • If the current character is uppercase, then increment the value of currentSum by 1. Otherwise, decrease the value of currentSum by -1.
    • If the value of currentSum is 0, then increment the value of res by 1.
    • If the value of currentSum exists in the map M, then increment the value of res by M[currentSum].
    • Increment the frequency of currentSum in the HashMap M by 1.
  • After completing the above steps, print the value of res as the result.

Below is the implementation of the above approach:

C++




// C++ program for the above approach
 
#include <bits/stdc++.h>
using namespace std;
 
// Function to find the count of
// substrings having an equal number
// of uppercase and lowercase characters
int countSubstring(string& S, int N)
{
    // Stores the count of prefixes
    // having sum S considering uppercase
    // and lowercase characters as 1 and -1
    unordered_map<int, int> prevSum;
 
    // Stores the count of substrings
    // having equal number of lowercase
    // and uppercase characters
    int res = 0;
 
    // Stores the sum obtained so far
    int currentSum = 0;
 
    for (int i = 0; i < N; i++) {
 
        // If the character is uppercase
        if (S[i] >= 'A' and S[i] <= 'Z') {
            currentSum++;
        }
 
        // Otherwise
        else
            currentSum--;
 
        // If currsum is o
        if (currentSum == 0)
            res++;
 
        // If the current sum exists in
        // the HashMap prevSum
        if (prevSum.find(currentSum)
            != prevSum.end()) {
 
            // Increment the resultant
            // count by 1
            res += (prevSum[currentSum]);
        }
 
        // Update the frequency of the
        // current sum by 1
        prevSum[currentSum]++;
    }
 
    // Return the resultant count of
    // the subarrays
    return res;
}
 
// Driver Code
int main()
{
    string S = "gEEk";
    cout << countSubstring(S, S.length());
 
    return 0;
}


Java




// Java program for the above approach
import java.util.HashMap;
 
class GFG{
 
// Function to find the count of
// substrings having an equal number
// of uppercase and lowercase characters
static int countSubstring(String S, int N)
{
     
    // Stores the count of prefixes
    // having sum S considering uppercase
    // and lowercase characters as 1 and -1
    HashMap<Integer, Integer> prevSum = new HashMap<>();
 
    // Stores the count of substrings
    // having equal number of lowercase
    // and uppercase characters
    int res = 0;
 
    // Stores the sum obtained so far
    int currentSum = 0;
 
    for(int i = 0; i < N; i++)
    {
         
        // If the character is uppercase
        if (S.charAt(i) >= 'A' && S.charAt(i) <= 'Z')
        {
            currentSum++;
        }
 
        // Otherwise
        else
            currentSum--;
 
        // If currsum is 0
        if (currentSum == 0)
            res++;
 
        // If the current sum exists in
        // the HashMap prevSum
        if (prevSum.containsKey(currentSum))
        {
             
            // Increment the resultant
            // count by 1
            res += prevSum.get(currentSum);
        }
 
        // Update the frequency of the
        // current sum by 1
        prevSum.put(currentSum,
                    prevSum.getOrDefault(currentSum, 0) + 1);
    }
 
    // Return the resultant count of
    // the subarrays
    return res;
}
 
// Driver Code
public static void main(String[] args)
{
    String S = "gEEk";
    System.out.println(countSubstring(S, S.length()));
}
}
 
// This code is contributed by abhinavjain194


Python3




# Python3 program for the above approach
 
# Function to find the count of
# substrings having an equal number
# of uppercase and lowercase characters
def countSubstring(S, N):
     
    # Stores the count of prefixes
    # having sum S considering uppercase
    # and lowercase characters as 1 and -1
    prevSum = {}
 
    # Stores the count of substrings
    # having equal number of lowercase
    # and uppercase characters
    res = 0
 
    # Stores the sum obtained so far
    currentSum = 0
 
    for i in range(N):
         
        # If the character is uppercase
        if (S[i] >= 'A' and S[i] <= 'Z'):
            currentSum += 1
 
        # Otherwise
        else:
            currentSum -= 1
 
        # If currsum is o
        if (currentSum == 0):
            res += 1
 
        # If the current sum exists in
        # the HashMap prevSum
        if (currentSum in prevSum):
             
            # Increment the resultant
            # count by 1
            res += (prevSum[currentSum])
 
        # Update the frequency of the
        # current sum by 1
        if currentSum in prevSum:
            prevSum[currentSum] += 1
        else:
            prevSum[currentSum] = 1
 
    # Return the resultant count of
    # the subarrays
    return res
 
# Driver Code
if __name__ == '__main__':
     
    S = "gEEk"
    print(countSubstring(S, len(S)))
 
# This code is contributed by bgangwar59


C#




// C# program for the above approach
using System;
using System.Collections.Generic;
 
class GFG{
 
// Function to find the count of
// substrings having an equal number
// of uppercase and lowercase characters
static int countSubstring(String S, int N)
{
     
    // Stores the count of prefixes
    // having sum S considering uppercase
    // and lowercase characters as 1 and -1
    Dictionary<int,
               int> prevSum = new Dictionary<int,
                                             int>();
 
    // Stores the count of substrings
    // having equal number of lowercase
    // and uppercase characters
    int res = 0;
 
    // Stores the sum obtained so far
    int currentSum = 0;
 
    for(int i = 0; i < N; i++)
    {
         
        // If the character is uppercase
        if (S[i] >= 'A' && S[i] <= 'Z')
        {
            currentSum++;
        }
 
        // Otherwise
        else
            currentSum--;
 
        // If currsum is 0
        if (currentSum == 0)
            res++;
 
        // If the current sum exists in
        // the Dictionary prevSum
        if (prevSum.ContainsKey(currentSum))
        {
             
            // Increment the resultant
            // count by 1
            res += prevSum[currentSum];
            prevSum[currentSum] = prevSum[currentSum] + 1;
        }
        else
            prevSum.Add(currentSum, 1);
    }
 
    // Return the resultant count of
    // the subarrays
    return res;
}
 
// Driver Code
public static void Main(String[] args)
{
    String S = "gEEk";
    Console.WriteLine(countSubstring(S, S.Length));
}
}
 
// This code is contributed by Princi Singh


Javascript




<script>
 
// Javascript program for the above approach
 
// Function to find the count of
// substrings having an equal number
// of uppercase and lowercase characters
function countSubstring(S, N)
{
    // Stores the count of prefixes
    // having sum S considering uppercase
    // and lowercase characters as 1 and -1
    var prevSum = new Map();
 
    // Stores the count of substrings
    // having equal number of lowercase
    // and uppercase characters
    var res = 0;
 
    // Stores the sum obtained so far
    var currentSum = 0;
 
    for (var i = 0; i < N; i++) {
 
        // If the character is uppercase
        if (S[i] >= 'A' && S[i] <= 'Z') {
            currentSum++;
        }
 
        // Otherwise
        else
            currentSum--;
 
        // If currsum is o
        if (currentSum == 0)
            res++;
 
        // If the current sum exists in
        // the HashMap prevSum
        if (prevSum.has(currentSum)) {
 
            // Increment the resultant
            // count by 1
            res += (prevSum.get(currentSum));
        }
 
        // Update the frequency of the
        // current sum by 1
        if(prevSum.has(currentSum))
            prevSum.set(currentSum, prevSum.get(currentSum)+1)
        else
            prevSum.set(currentSum, 1)
    }
 
    // Return the resultant count of
    // the subarrays
    return res;
}
 
// Driver Code
var S = "gEEk";
document.write( countSubstring(S, S.length));
 
</script>


Output: 

3

 

Time Complexity: O(N)
Auxiliary Space: O(N) because map prevSum will be taking extra space


My Personal Notes arrow_drop_up
Like Article
Save Article
Related Articles

Start Your Coding Journey Now!