Given a string s , consisting only of characters 'a' , 'b' , 'c'.Find the number of substrings that contain at least one occurrence of all these characters 'a' , 'b' , 'c'.
Input : s = "abcba"
Output : 5
Explanation : The substrings containing at least one occurrence of the characters 'a' , 'b' , 'c' are "abc" , "abcb" , "abcba" , "bcba" , "cba".
Input : s = "ccabcc"
Output : 8
Explanation : The substrings containing at least one occurrence of the characters 'a' , 'b' , 'c' are "ccab" , "ccabc" , "ccabcc" , "cab" , "cabc" , "cabcc" , "abc" , "abcc".
Input : s = "abccba"
Here, the idea is to find all possible substrings of the given string and while doing so, mark the presence of each character in the hash array. If 'a', 'b', 'c' are present in the current subarray increment the count and finally return it.
#include <bits/stdc++.h>
using namespace std;
class Solution {
public:
/* Function to find the number of substrings
containing all characters 'a', 'b', 'c' in string s. */
int numberOfSubstrings(string s) {
int count = 0;
// Iterate through each starting point of substring
for (int i = 0; i < s.size(); ++i) {
// Array to track presence of 'a', 'b', 'c'
int hash[3] = {0};
// Iterate through each ending point of substring
for (int j = i; j < s.size(); ++j) {
// Mark current character in hash
hash[s[j] - 'a'] = 1;
/* Check if all characters
'a', 'b', 'c' are present*/
if (hash[0] + hash[1] + hash[2] == 3) {
// Increment count for valid substring
count++;
}
}
}
// Return the total count of substrings
return count;
}
};
int main() {
string s = "bbacba";
// Create an instance of Solution class
Solution sol;
int ans = sol.numberOfSubstrings(s);
// Print the result
cout << "Number of substrings containing 'a', 'b', 'c' in \"" << s << "\" is: " << ans << endl;
return 0;
}
import java.util.*;
class Solution {
/* Function to find the number of substrings
containing all characters 'a', 'b', 'c' in string s. */
public int numberOfSubstrings(String s) {
int count = 0;
// Iterate through each starting point of substring
for (int i = 0; i < s.length(); ++i) {
// Array to track presence of 'a', 'b', 'c'
int[] hash = new int[3];
// Iterate through each ending point of substring
for (int j = i; j < s.length(); ++j) {
// Mark current character in hash
hash[s.charAt(j) - 'a'] = 1;
/* Check if all characters
'a', 'b', 'c' are present*/
if (hash[0] + hash[1] + hash[2] == 3) {
// Increment count for valid substring
count++;
}
}
}
// Return the total count of substrings
return count;
}
public static void main(String[] args) {
String s = "bbacba";
// Create an instance of Solution class
Solution sol = new Solution();
int ans = sol.numberOfSubstrings(s);
// Print the result
System.out.println("Number of substrings containing 'a', 'b', 'c' in \"" + s + "\" is: " + ans);
}
}
class Solution:
""" Function to find the number of substrings
containing all characters 'a', 'b', 'c' in string s. """
def numberOfSubstrings(self, s: str) -> int:
count = 0
# Iterate through each starting point of substring
for i in range(len(s)):
# Array to track presence of 'a', 'b', 'c'
hash = [0, 0, 0]
# Iterate through each ending point of substring
for j in range(i, len(s)):
# Mark current character in hash
hash[ord(s[j]) - ord('a')] = 1
# Check if all characters 'a', 'b', 'c' are present
if sum(hash) == 3:
# Increment count for valid substring
count += 1
# Return the total count of substrings
return count
if __name__ == "__main__":
s = "bbacba"
# Create an instance of Solution class
sol = Solution()
ans = sol.numberOfSubstrings(s)
# Print the result
print(f"Number of substrings containing 'a', 'b', 'c' in \"{s}\" is: {ans}")
class Solution {
/* Function to find the number of substrings
containing all characters 'a', 'b', 'c' in string s. */
numberOfSubstrings(s) {
let count = 0;
// Iterate through each starting point of substring
for (let i = 0; i < s.length; ++i) {
// Array to track presence of 'a', 'b', 'c'
let hash = [0, 0, 0];
// Iterate through each ending point of substring
for (let j = i; j < s.length; ++j) {
// Mark current character in hash
hash[s.charCodeAt(j) - 'a'.charCodeAt(0)] = 1;
/* Check if all characters
'a', 'b', 'c' are present*/
if (hash[0] + hash[1] + hash[2] === 3) {
// Increment count for valid substring
count++;
}
}
}
// Return the total count of substrings
return count;
}
}
let s = "bbacba";
// Create an instance of Solution class
let sol = new Solution();
let ans = sol.numberOfSubstrings(s);
// Print the result
console.log(`Number of substrings containing 'a', 'b', 'c' in "${s}" is: ${ans}`);
The idea here is to use a for loop to iterate through the array, as moving forward in the array update the last seen of 'a', 'b', 'c' in the hash array. Now, check if the current substring has atleast one of each 'a', 'b', 'c', if so, then the previous substrings must be having these characters too, so add all such substrings in the count varaible and return it.
lastSeen
of size 3 ({-1, -1, -1}) to store the last seen index of characters 'a', 'b', 'c' respectively, count
to 0 to keep track of the number of valid substrings found.Please refer to the video for complete dry-run.
#include <bits/stdc++.h>
using namespace std;
class Solution {
public:
/* Function to find the number of substrings
containing all characters 'a', 'b', 'c' in string s. */
int numberOfSubstrings(string s) {
/* Array to store the last seen
index of characters 'a', 'b', 'c'*/
int lastSeen[3] = {-1, -1, -1};
int count = 0;
// Iterate through each character in string s
for (int i = 0; i < s.size(); ++i) {
// Update lastSeen index for
lastSeen[s[i] - 'a'] = i;
/* Check if all characters 'a',
'b', 'c' have been seen*/
if (lastSeen[0] != -1 && lastSeen[1] != -1 && lastSeen[2] != -1) {
/* Count valid substrings
ending at current index*/
count += 1 + min({lastSeen[0], lastSeen[1], lastSeen[2]});
}
}
// Return total count of substrings
return count;
}
};
int main() {
string s = "bbacba";
// Create an instance of Solution class
Solution sol;
int ans = sol.numberOfSubstrings(s);
// Print the result
cout << "Number of substrings containing 'a', 'b', 'c' in \"" << s << "\" is: " << ans << endl;
return 0;
}
class Solution {
/* Function to find the number of substrings
containing all characters 'a', 'b', 'c' in string s. */
public int numberOfSubstrings(String s) {
/* Array to store the last seen
index of characters 'a', 'b', 'c'*/
int[] lastSeen = {-1, -1, -1};
int count = 0;
// Iterate through each character in string s
for (int i = 0; i < s.length(); ++i) {
// Update lastSeen index
lastSeen[s.charAt(i) - 'a'] = i;
/* Check if all characters 'a',
'b', 'c' have been seen*/
if (lastSeen[0] != -1 && lastSeen[1] != -1 && lastSeen[2] != -1) {
/* Count valid substrings
ending at current index*/
count += 1 + Math.min(Math.min(lastSeen[0], lastSeen[1]), lastSeen[2]);
}
}
// Return the total count of substrings
return count;
}
public static void main(String[] args) {
String s = "bbacba";
// Create an instance of Solution class
Solution sol = new Solution();
int ans = sol.numberOfSubstrings(s);
// Print the result
System.out.println("Number of substrings containing 'a', 'b', 'c' in \"" + s + "\" is: " + ans);
}
}
class Solution:
""" Function to find the number of substrings
containing all characters 'a', 'b', 'c' in string s. """
def numberOfSubstrings(self, s: str) -> int:
"""Array to store the last seen
index of characters 'a', 'b', 'c'"""
last_seen = [-1, -1, -1]
count = 0
# Iterate through each character in string s
for i in range(len(s)):
""" Update last_seen index
for current character"""
last_seen[ord(s[i]) - ord('a')] = i
""" Check if all characters 'a',
'b', 'c' have been seen"""
if last_seen[0] != -1 and last_seen[1] != -1 and last_seen[2] != -1:
""" Count valid substrings
ending at current index"""
count += 1 + min(last_seen[0], last_seen[1], last_seen[2])
# Return the total count of substrings
return count
# Test the solution
if __name__ == "__main__":
s = "bbacba"
# Create an instance of Solution class
sol = Solution()
ans = sol.numberOfSubstrings(s)
# Print the result
print(f"Number of substrings containing 'a', 'b', 'c' in \"{s}\" is: {ans}")
class Solution {
/* Function to find the number of substrings
containing all characters 'a', 'b', 'c' in string s. */
numberOfSubstrings(s) {
/* Array to store the last seen
index of characters 'a', 'b', 'c'*/
let lastSeen = [-1, -1, -1];
let count = 0;
// Iterate through each character in string s
for (let i = 0; i < s.length; ++i) {
// Update lastSeen index for current character
lastSeen[s.charCodeAt(i) - 'a'.charCodeAt(0)] = i;
/* Check if all characters 'a',
'b', 'c' have been seen*/
if (lastSeen[0] !== -1 && lastSeen[1] !== -1 && lastSeen[2] !== -1) {
/* Count valid substrings
ending at current index*/
count += 1 + Math.min(lastSeen[0], lastSeen[1], lastSeen[2]);
}
}
// Return the total count of substrings
return count;
}
}
// Test the solution
let s = "bbacba";
// Create an instance of Solution class
let sol = new Solution();
let ans = sol.numberOfSubstrings(s);
// Print the result
console.log(`Number of substrings containing 'a', 'b', 'c' in "${s}" is: ${ans}`);
Q: Why does shrinking the window work?
A: Once a window satisfies the condition, shrinking it ensures you explore the smallest valid substrings while maintaining all necessary characters. This reduces redundant checks.
Q: What happens if characters appear in large consecutive blocks (e.g., "aaaabbbbcccc")?
A: The algorithm efficiently calculates valid substrings without enumerating all possible substrings. It dynamically counts substrings for each valid window, avoiding unnecessary computations.
Q: How would you extend this to handle more characters?
A: For more characters, increase the size of the frequency map and apply the same sliding window logic. The algorithm's efficiency remains linear, as the fixed size of the map ensures constant-time updates.
Q: What if the problem asks for exactly one occurrence of each character in the substring?
A: Modify the frequency map check to ensure each character has exactly one count in the current window before counting substrings.