Open In App

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

Improve
Improve
Like Article
Like
Save
Share
Report

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.

Steps that were to follow the above approach:

  • We will traverse the array using two for loops
  • We will take ans variable to 0, to store answer.
  • In each iteration we will set lower and upper as 0.
  • If a upper case come then we will increase the upper else we will increase the lower
  • If upper and lower become equal then we will increase the count of our answer by 1
  • In last we will return the ans variable.

Below is the code to implement the above steps:

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)
{
      //Variable to store answer and count
      //lower and upper case alphabets
    int ans=0,lower=0,upper=0;
   
      //iterating
    for(int i=0;i<S.length();i++){
      //setting lower and upper to 0
      upper=0;
      lower=0;
       
      for(int j=i;j<S.length();j++){
        //if upper case le==alphabet
        if(isupper(S[j]))upper++;
         
        else lower++;
        //if lower and upper are equal
        if(upper==lower)ans++;
         
      }
       
    }
    return ans;
}
 
// Driver Code
int main()
{
    string S = "gEEk";
    cout << countSubstring(S, S.length());
 
    return 0;
}
//code contributed by shubhamrajput6156


Java




// Java program for the above approach
import java.util.*;
 
class Main {
// Function to find the count of
// substrings having an equal number
// of uppercase and lowercase characters
public static int countSubstring(String S, int N) {
// Variable to store answer and count
// lower and upper case alphabets
int ans = 0, lower = 0, upper = 0;
    // iterating
    for (int i = 0; i < S.length(); i++) {
        // setting lower and upper to 0
        upper = 0;
        lower = 0;
 
        for (int j = i; j < S.length(); j++) {
            // if upper case le==alphabet
            if (Character.isUpperCase(S.charAt(j)))
                upper++;
            else
                lower++;
            // if lower and upper are equal
            if (upper == lower)
                ans++;
        }
    }
    return ans;
}
 
// Driver Code
public static void main(String args[]) {
    String S = "gEEk";
    System.out.println(countSubstring(S, S.length()));
}
}
 
//Code contributed by Vaibhav


Python3




# Convert to python code
 
# Function to find the count of substrings having an equal
# number of uppercase and lowercase characters
def countSubstring(S):
    # Variable to store answer and count lower and upper case alphabets
    ans, lower, upper = 0, 0, 0
 
    # iterating
    for i in range(len(S)):
        # setting lower and upper to 0
        upper = 0
        lower = 0
 
        for j in range(i, len(S)):
            # if upper case alphabet
            if S[j].isupper():
                upper += 1
            else:
                lower += 1
            # if lower and upper are equal
            if upper == lower:
                ans += 1
 
    return ans
 
# Driver Code
S = "gEEk"
print(countSubstring(S))
 
# The code is contributed by Nidhi goel.


C#




using System;
 
public class GFG
{
    // Function to find the count of substrings having an equal
    // number of uppercase and lowercase characters
    public static int CountSubstring(string S)
    {
        // Variable to store the answer and count lower and upper
       // case alphabets
        int ans = 0, lower = 0, upper = 0;
 
        // Iterating through the string
        for (int i = 0; i < S.Length; i++)
        {
            // Resetting lower and upper to 0 for each iteration
            upper = 0;
            lower = 0;
 
            for (int j = i; j < S.Length; j++)
            {
                // If it's an upper case alphabet
                if (Char.IsUpper(S[j]))
                {
                    upper++;
                }
                else
                {
                    lower++;
                }
 
                // If the count of lower and upper case characters
               // are equal
                if (upper == lower)
                {
                    ans++;
                }
            }
        }
 
        return ans;
    }
 
    public static void Main(string[] args)
    {
        string S = "gEEk";
        Console.WriteLine(CountSubstring(S));
    }
}


Javascript




// Function to find the count of substrings having an equal number of uppercase and lowercase characters
function countSubstring(S, N) {
    // Variable to store answer and count lower and upper case alphabets
    let ans = 0,
        lower = 0,
        upper = 0;
 
    // iterating
    for (let i = 0; i < S.length; i++) {
        // setting lower and upper to 0
        upper = 0;
        lower = 0;
 
        for (let j = i; j < S.length; j++) {
            // if upper case alphabet
            if (S[j] === S[j].toUpperCase()) upper++;
            else lower++;
            // if lower and upper are equal
            if (upper == lower) ans++;
        }
    }
    return ans;
}
 
// Driver Code
let S = "gEEk";
console.log(countSubstring(S, S.length));


Output

3

Time Complexity: O(N^2)
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



Last Updated : 02 Aug, 2023
Like Article
Save Article
Previous
Next
Share your thoughts in the comments
Similar Reads