Data Structure
Networking
RDBMS
Operating System
Java
MS Excel
iOS
HTML
CSS
Android
Python
C Programming
C++
C#
MongoDB
MySQL
Javascript
PHP
- Selected Reading
- UPSC IAS Exams Notes
- Developer's Best Practices
- Questions and Answers
- Effective Resume Writing
- HR Interview Questions
- Computer Glossary
- Who is Who
Count of substrings with the frequency of at most one character as Odd
Substrings are the subsets or sequences of contiguous characters of a string.
Now, in this problem, we need to find the number of substrings with the frequency of at most one character as odd. Let us see how we should proceed to solve this problem.
Let's try to understand this problem with the help of some examples.
Input
s = "ksjssjkk"
Output
21
Explanation As the frequency of the characters in the given string is given below
k → 3
s → 3
j → 2
Now, substrings with at most one character occurring at an odd number of time times can be
Take each character: ?k', ?s', ?j', ?s', ?s', ?j', ?k', ?k' = 8
Take 2 letters at a time: ?ss', ?kk' = 2
Take 3 letters at a time: ?sjs', ?jss', ?ssj', ?jkk' = 4
Take 4 letters at a time: ?jssj' = 1
Take 5 letters at a time: ?sjssj', ?jssjk', ?ssjkk' = 3
Take 6 letters at a time: ?jssjkk' = 1
Take 7 letters at a time: ?ksjssjk', ?sjssjkk' = 2
Take 8 letters at a time: No string
Now, adding the number of substrings we get (8 + 2 + 4 + 1 + 3 + 1 + 2) = 21
Input
s = "ab"
Output
2
Explanation 2 substrings we will get are: ?a', ?b'
Problem Explanation
Let's try to understand the problem and find its solution. We have to find those substrings in the string where at most, one letter appears an odd number of times, i.e., in whole, there is at most one letter whose frequency is odd.
Solution-1: Brute Force Solution
Approach
This is an easy-to-understand approach. We will simply run loops to get access to all substrings and we will keep on checking if there is only one letter with odd frequency or not. If yes, we will include the substring in our final output.
Example
The following are implementations of the above approach in various programming languages
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdbool.h>
bool checkValid(const char* s){
int n = strlen(s);
// Define Frequency vector
int Freq[26] = {0};
// Define a variable named oddFreq to calculate total odd frequencies
int oddFreq = 0;
// Run a loop to count the frequencies of each character
for (int i = 0; i < n; i++) {
if (s[i] >= 'a' && s[i] <= 'z') {
Freq[s[i] - 'a']++;
}
}
// Run a loop to calculate the number of frequencies that are odd
for (int i = 0; i < 26; i++) {
if (Freq[i] % 2 != 0)
oddFreq++;
}
// Check if the frequency of any character is odd in number more than one then return false, else return true
if (oddFreq <= 1) return true;
else return false;
}
// Function to count the number of substrings with the frequency of at most one character as Odd
int Helper(const char* s){
// Define the size of the string
int n = strlen(s);
// Define a variable output initiated by zero
int output = 0;
// Run a loop to traverse through the string
for(int i = 0; i < n; i++) {
// Run another loop inside the first loop to get substrings
for (int j = i; j < n; j++) {
// Get substring from i to j
char S[100]; // Use an array to store the substring
strncpy(S, s + i, j - i + 1);
S[j - i + 1] = '\0'; // Null-terminate the substring
if (checkValid(S)) output++;
}
}
// Return the final output
return output;
}
int main(){
const char* s = "ksjssjkk";
// Call the helper function to get the final output
int output = Helper(s);
// Print the output
printf("The number of substrings with the frequency of at most one character as Odd is: %d", output);
return 0;
}
Output
The number of substrings with the frequency of at most one character as Odd is: 21
#include <bits/stdc++.h>
using namespace std;
// Function which will check the string is valid
bool checkValid(string s){
int n = s.size();
// Define Frequency vector
int Freq[26] = {0};
// Define a variable named oddFreq to calculate total odd frequencies
int oddFreq = 0;
// Run a loop to count the frequencies of each character
for (int i = 0; i < n; i++) {
Freq[s[i] - 'a']++;
}
// Run a loop to calculate the number of frequencies that are odd
for (int i = 0; i < 26; i++) {
if (Freq[i] % 2 != 0)
oddFreq++;
}
// Check if the frequency of any character is odd in number more than one then return false, else return true
if (oddFreq <= 1) return true;
else return false;
}
// Function to count the number of substrings with the frequency of at most one character as Odd
int Helper(string s){
// Define the size of the string
int n = s.size();
// Define a variable output initiated by zero
int output = 0;
// Run a loop to traverse through the string
for(int i = 0; i < n; i++) {
// Run another loop inside the first loop to get substrings
for (int j = i; j < n; j++) {
// Get substring from i to j
string S = s.substr(i, j - i + 1);
if (checkValid(S)) output++;
}
}
// Return the final output
return output;
}
int main(){
// Give input string by the user
string s = "ksjssjkk" ;
// Call the helper function to get the final output
int output = Helper(s);
// Print the output
cout << "The number of substrings with the frequency of at most one character as Odd is: " << output;
return 0;
}
Output
The number of substrings with the frequency of at most one character as Odd is: 21
public class Main {
public static boolean checkValid(String s) {
int n = s.length();
// Define Frequency vector
int[] Freq = new int[26];
// Define a variable named oddFreq to calculate total odd frequencies
int oddFreq = 0;
// Run a loop to count the frequencies of each character
for (int i = 0; i < n; i++) {
Freq[s.charAt(i) - 'a']++;
}
// Run a loop to calculate the number of frequencies that are odd
for (int i = 0; i < 26; i++) {
if (Freq[i] % 2 != 0)
oddFreq++;
}
// Check if the frequency of any character is odd in number more than one then return false, else return true
return oddFreq <= 1;
}
// Function to count the number of substrings with the frequency of at most one character as Odd
public static int Helper(String s) {
// Define the size of the string
int n = s.length();
// Define a variable output initiated by zero
int output = 0;
// Run a loop to traverse through the string
for (int i = 0; i < n; i++) {
// Run another loop inside the first loop to get substrings
for (int j = i; j < n; j++) {
// Get substring from i to j
String S = s.substring(i, j + 1); // Corrected to use substring
if (checkValid(S)) output++;
}
}
return output;
}
public static void main(String[] args) {
// Give input string by the user
String s = "ksjssjkk";
// Call the helper function to get the final output
int output = Helper(s);
// Print the output
System.out.println("The number of substrings with the frequency of at most one character as Odd is: " + output);
}
}
Output
The number of substrings with the frequency of at most one character as Odd is: 21
# Function to check if the string is valid
def checkValid(s):
n = len(s)
# Define a frequency vector
Freq = [0] * 26
# Define a variable named oddFreq to calculate total odd frequencies
oddFreq = 0
# Run a loop to count the frequencies of each character
for i in range(n):
Freq[ord(s[i]) - ord('a')] += 1
# Run a loop to calculate the number of frequencies that are odd
for i in range(26):
if Freq[i] % 2 != 0:
oddFreq += 1
# Check if the frequency of any character is odd in number more than one then return False, else return True
return oddFreq <= 1
# Function to count the number of substrings with the frequency of at most one character as Odd
def Helper(s):
n = len(s)
# Define a variable output initiated by zero
output = 0
# Run a loop to traverse through the string
for i in range(n):
# Run another loop inside the first loop to get substrings
for j in range(i, n):
# Get substring from i to j
S = s[i:j+1]
if checkValid(S):
output += 1
# Return the final output
return output
def main():
# Give input string
s = "ksjssjkk"
# Call the Helper function to get the final output
output = Helper(s)
# Print the output
print("The number of substrings with the frequency of at most one character as Odd is:", output)
if __name__ == "__main__":
main()
Output
The number of substrings with the frequency of at most one character as Odd is: 21
Complexities for the above code
Time complexity O(n^3); where n is the size of the string, here (n^3) is the time complexity of the helper function while the checkValid function itself takes (O(n)) time to execute.
Space complexity O(1); We have not stored any variable in some data structure in the above code.
Solution-2: Optimized Solution using Bit-masking
Bit-masking
Bitmasking is the act of applying a mask over a value to keep, change or modify a piece of given information. A mask determines which bits to take and which bits to clear off a binary number. It can be used to mask a value to represent the subsets of a set using various bitwise operations.
Approach
We use a bitmask to indicate what characters are used the odd number of times, and we use a hashmap to keep track of previously seen bitmasks. We will increase the hashmap[bitmask] by one after each iteration, indicating that we are acquainted with this bitmask. The substrings with an even number of letters utilized will be counted when output += m[mask]. while output+= m[mask^ (1<<j)] will count the substrings when precisely one letter appears odd times.
Example
The following are implementations of the above approach in various programming languages
#include <bits/stdc++.h>
using namespace std;
int Helper(string s){
// Declare an Unordered map which would tell us if the frequency of bitmasks is odd or even that is 0 if that character has occurred even times and 1 if it has occurred odd times
unordered_map<int, int> m;
// Initiate the frequency bitmask
m[0] = 1;
// Store the current bitmask
int mask = 0;
// Initialize the output as 0
int output = 0;
// Run a loop to start masking
for (int i = 0; i < s.size(); ++i) {
// masking the current character
mask ^= (1 << (s[i] - 'a'));
// Count the substrings that have all alphabets used even the number of times
output += m[mask];
for (int j = 0; j < 26; ++j) {
// Count the substrings that have exactly 1 used character
output += m[mask ^ (1 << j)];
}
m[mask]++;
}
// Return the final output
return output;
}
int main(){
// Give input string by the user
string s = "ksjssjkk" ;
// Call the helper function to get the final output
int output = Helper(s);
// Print the output
cout << "The number of substrings with the frequency of at most one character as Odd is: " << output;
return 0;
}
Output
The number of substrings with the frequency of at most one character as Odd is: 21
import java.util.HashMap;
public class Main {
public static int Helper(String s) {
HashMap<Integer, Integer> m = new HashMap<>();
// Initiate the frequency bitmask
m.put(0, 1);
// Store the current bitmask
int mask = 0;
int output = 0;
// Run a loop to start masking
for (int i = 0; i < s.length(); i++) {
// masking the current character
mask ^= (1 << (s.charAt(i) - 'a'));
// Count the substrings that have all alphabets used even the number of times
output += m.getOrDefault(mask, 0);
for (int j = 0; j < 26; j++) {
// Count the substrings that have exactly 1 used character
output += m.getOrDefault(mask ^ (1 << j), 0);
}
m.put(mask, m.getOrDefault(mask, 0) + 1);
}
// Return the final output
return output;
}
public static void main(String[] args) {
// Give input string by the user
String s = "ksjssjkk";
// Call the helper function to get the final output
int output = Helper(s);
System.out.println("The number of substrings with the frequency of at most one character as Odd is: " + output);
}
}
Output
The number of substrings with the frequency of at most one character as Odd is: 21
def Helper(s):
# Initiate the frequency bitmask
m = {0: 1}
# Store the current bitmask
mask = 0
output = 0
# Run a loop to start masking
for i in range(len(s)):
# masking the current character
mask ^= (1 << (ord(s[i]) - ord('a')))
# Count the substrings that have all alphabets used even the number of times
output += m.get(mask, 0)
for j in range(26):
# Count the substrings that have exactly 1 used character
output += m.get(mask ^ (1 << j), 0)
m[mask] = m.get(mask, 0) + 1
# Return the final output
return output
def main():
# Give input string by the user
s = "ksjssjkk"
# Call the helper function to get the final output
output = Helper(s)
print("The number of substrings with the frequency of at most one character as Odd is:",output)
if __name__ == "__main__":
main()
Output
The number of substrings with the frequency of at most one character as Odd is: 21
Complexities for the Above Code
Time complexity O(n*26); where n is the size of the string. As for each character of the string, we have a check for 26 total characters.
Space complexity O(1); We used a map data structure only which would occupy O(26) space which is relatively equal to O(1) space complexity.
Conclusion
In this article, to find the number of substrings with the frequency of at most one character as odd. Firstly, we will apply the naive approach to get the output using loops, it is an easy-to-understand approach but the only drawback of that approach is that it will be executed with a huge time complexity. However, we can easily deduce the time complexity of the code by using another technique called bitmasking using hashmaps. This question, in particular, is a peculiar example of the application of bitmasking technique as it deduced time complexity from O(n^3) to O(n). In this article, we learned the use and concepts of bitmasking.