Good characters
Last Updated :
17 Jan, 2024
Given a strings A of length N and an integer K. Consider any substring S of A, a character C is said good if: 2*(frequency of C in S) – Length of Substring = K find the sum of count of all good characters across all the substrings of string A.
Example:
Input: N=4 K=0 A=abcd
Output: 6
Input: N=4 K=-1 A=abac
Output: 4
The idea is to fix a character and count the number of substrings it is good for. This can be done by using prefix sums and a map to store the smallest character and its frequency in each range.
Here’s a step-by-step breakdown of the idea:
- Fix a character: Fix a character, say ‘a’. This means we are trying to find all substrings where ‘a’ is the smallest character and occurs exactly once.
- Count the number of substrings: For each fixed character (‘a’ in this case), count the number of substrings it is good for. A substring is considered good if the condition 2 * (frequency of in the substring) – Length of Substring = 2*(frequency of a in the substring)-Length of Substring=K is satisfied.
- Use prefix sum: Prefix sum are used to quickly calculate the sum of elements in a given range. In this case, we use prefix sums to keep track of the frequency of each character in the string.
- Use a map: A map is used to store the smallest character and its frequency in each range. This helps us quickly identify if the fixed character is the smallest in a given range and if it occurs exactly once.
- Repeat for all characters: We repeat steps 1-4 for all characters in the string. The total count of good characters is the sum of the counts for each character.
Step-by-step approach:
- Initialize the answer (ans) to zero.
- Iterate over each character (‘a’ to ‘z’).
- For each character, maintain a frequency array (mp) initialized with one occurrence at the middle index.
- Traverse the input string, updating the occurrence count and total at each step.
- Use prefix sum array (prefixSum) to efficiently calculate the sum of characters in the current substring.
- Update the answer by adding the count of good characters based on the conditions specified in the problem.
- Output the final result.
Below is the implementation of the above approach:
C++
#include <bits/stdc++.h>
using namespace std;
const int MAX_CHARS = 26;
int countGoodCharacters(string A, int K)
{
int n = A.length();
long long ans = 0;
for ( int o = 0; o < MAX_CHARS; o++) {
int mp[2 * n + 1]
= { 0 };
mp[n]++;
int occurrence = 0;
int total = n;
vector< int > prefixSum(n + 1, n);
for ( int i = 0; i < n; i++) {
int x = (A[i] == 'a' + o) ? 1 : -1;
occurrence += x;
total += x;
prefixSum[i + 1] = total;
ans += mp[total - K];
if (K < 0 && (i + 1 + K >= 0)
&& (prefixSum[i + 1 + K] == total - K))
ans--;
mp[total]++;
}
}
return ans;
}
int main()
{
int N = 4, K = -1;
string A = "abac" ;
long long result = countGoodCharacters(A, K);
cout << result << endl;
return 0;
}
|
Java
import java.util.*;
public class GoodCharacters {
static final int MAX_CHARS = 26 ;
static long countGoodCharacters(String A, int K) {
int n = A.length();
long ans = 0 ;
for ( int o = 0 ; o < MAX_CHARS; o++) {
int [] mp = new int [ 2 * n + 1 ];
Arrays.fill(mp, 0 );
mp[n]++;
int occurrence = 0 ;
int total = n;
int [] prefixSum = new int [n + 1 ];
Arrays.fill(prefixSum, n);
for ( int i = 0 ; i < n; i++) {
int x = (A.charAt(i) == 'a' + o) ? 1 : - 1 ;
occurrence += x;
total += x;
prefixSum[i + 1 ] = total;
ans += mp[total - K];
if (K < 0 && (i + 1 + K >= 0 ) && (prefixSum[i + 1 + K] == total - K))
ans--;
mp[total]++;
}
}
return ans;
}
public static void main(String[] args) {
int N = 4 , K = - 1 ;
String A = "abac" ;
long result = countGoodCharacters(A, K);
System.out.println(result);
}
}
|
Python3
MAX_CHARS = 26
def count_good_characters(A, K):
n = len (A)
ans = 0
for o in range (MAX_CHARS):
mp = [ 0 ] * ( 2 * n + 1 )
mp[n] = 1
occurrence = 0
total = n
prefix_sum = [n] * (n + 1 )
for i in range (n):
x = 1 if A[i] = = chr ( ord ( 'a' ) + o) else - 1
occurrence + = x
total + = x
prefix_sum[i + 1 ] = total
ans + = mp[total - K]
if K < 0 and (i + 1 + K > = 0 ) and (prefix_sum[i + 1 + K] = = total - K):
ans - = 1
mp[total] + = 1
return ans
def main():
N, K = 4 , - 1
A = "abac"
result = count_good_characters(A, K)
print (result)
if __name__ = = "__main__" :
main()
|
C#
using System;
using System.Collections.Generic;
class MainClass
{
const int MAX_CHARS = 26;
static long CountGoodCharacters( string A, int K)
{
int n = A.Length;
long ans = 0;
for ( int o = 0; o < MAX_CHARS; o++)
{
int [] mp = new int [2 * n + 1];
Array.Fill(mp, 0);
mp[n]++;
int occurrence = 0;
int total = n;
List< int > prefixSum = new List< int >( new int [n + 1]);
prefixSum[0] = n;
for ( int i = 0; i < n; i++)
{
int x = (A[i] == 'a' + o) ? 1 : -1;
occurrence += x;
total += x;
prefixSum[i + 1] = total;
ans += mp[total - K];
if (K < 0 && (i + 1 + K >= 0) && (prefixSum[i + 1 + K] == total - K))
ans--;
mp[total]++;
}
}
return ans;
}
public static void Main( string [] args)
{
int K = -1;
string A = "abac" ;
long result = CountGoodCharacters(A, K);
Console.WriteLine(result);
}
}
|
Javascript
const MAX_CHARS = 26;
function countGoodCharacters(A, K) {
const n = A.length;
let ans = 0;
for (let o = 0; o < MAX_CHARS; o++) {
const mp = new Array(2 * n + 1).fill(0);
mp[n]++;
let occurrence = 0;
let total = n;
const prefixSum = new Array(n + 1).fill(0);
prefixSum[0] = n;
for (let i = 0; i < n; i++) {
const x = A[i] === String.fromCharCode( 'a' .charCodeAt(0) + o) ? 1 : -1;
occurrence += x;
total += x;
prefixSum[i + 1] = total;
ans += mp[total - K];
if (K < 0 && i + 1 + K >= 0 && prefixSum[i + 1 + K] === total - K)
ans--;
mp[total]++;
}
}
return ans;
}
const K = -1;
const A = "abac" ;
const result = countGoodCharacters(A, K);
console.log(result);
|
Time complexity: O(N * M), where N is the length of the input string s and M is the size of the alphabet (26 characters).
Auxiliary Space: O(M), where M is the size of the alphabet.
Share your thoughts in the comments
Please Login to comment...