Number of substrings having an equal number of lowercase and uppercase letters
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:
- “gE”
- “gEEk”
- “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> |
3
Time Complexity: O(N)
Auxiliary Space: O(N) because map prevSum will be taking extra space
Please Login to comment...