Count of distinct characters in a substring by given range for Q queries
Last Updated :
01 Nov, 2023
Given a string S consisting of lower case alphabets of size N and Q queries in the range [L, R], the task is to print the count of distinct characters in the substring by given range for each query.
Examples:
Input: S = “geeksforgeeks”, Q[][] = {{0, 4}, {3, 7}}
Output:
4
5
Explanation:
Distinct characters in substring S[0:4] are ‘g’, ‘e’, ‘k’ and ‘s’
Distinct characters in substring in S[3:7] are ‘k’, ‘s’ ‘f’, ‘o’ and ‘r’
Input: S = “geeksforgeeksisacomputerscienceportal”, Q[][] = {{0, 10}, {15, 18}, {12, 20}}
Output:
7
4
8
Naive Approach: The idea is to use hashing to maintain the frequency of each character in the given substring and then count the characters with a frequency equal to 1.
Below is the implementation of the above approach:
C++
#include <bits/stdc++.h>
using namespace std;
void findCount(string s, int L, int R)
{
int distinct = 0;
int frequency[26] = {};
for ( int i = L; i <= R; i++) {
frequency[s[i] - 'a' ]++;
}
for ( int i = 0; i < 26; i++) {
if (frequency[i] > 0)
distinct++;
}
cout << distinct << endl;
}
int main()
{
string s = "geeksforgeeksisacomputerscienceportal" ;
int queries = 3;
int Q[queries][2] = { { 0, 10 },
{ 15, 18 },
{ 12, 20 } };
for ( int i = 0; i < queries; i++)
findCount(s, Q[i][0], Q[i][1]);
return 0;
}
|
Java
class GFG{
static void findCount(String s, int L,
int R)
{
int distinct = 0 ;
int []frequency = new int [ 26 ];
for ( int i = L; i <= R; i++)
{
frequency[s.charAt(i) - 'a' ]++;
}
for ( int i = 0 ; i < 26 ; i++)
{
if (frequency[i] > 0 )
distinct++;
}
System.out.print(distinct + "\n" );
}
public static void main(String[] args)
{
String s = "geeksforgeeksisa" +
"computerscienceportal" ;
int queries = 3 ;
int Q[][] = { { 0 , 10 },
{ 15 , 18 },
{ 12 , 20 } };
for ( int i = 0 ; i < queries; i++)
findCount(s, Q[i][ 0 ], Q[i][ 1 ]);
}
}
|
Python3
def findCount(s, L, R):
distinct = 0
frequency = [ 0 for i in range ( 26 )]
for i in range (L, R + 1 , 1 ):
frequency[ ord (s[i]) - ord ( 'a' )] + = 1
for i in range ( 26 ):
if (frequency[i] > 0 ):
distinct + = 1
print (distinct)
if __name__ = = '__main__' :
s = "geeksforgeeksisacomputerscienceportal"
queries = 3
Q = [ [ 0 , 10 ],
[ 15 , 18 ],
[ 12 , 20 ] ]
for i in range (queries):
findCount(s, Q[i][ 0 ], Q[i][ 1 ])
|
C#
using System;
class GFG{
static void findCount(String s, int L,
int R)
{
int distinct = 0;
int []frequency = new int [26];
for ( int i = L; i <= R; i++)
{
frequency[s[i] - 'a' ]++;
}
for ( int i = 0; i < 26; i++)
{
if (frequency[i] > 0)
distinct++;
}
Console.Write(distinct + "\n" );
}
public static void Main(String[] args)
{
String s = "geeksforgeeksisa" +
"computerscienceportal" ;
int queries = 3;
int [,]Q = {{ 0, 10 },
{ 15, 18 },
{ 12, 20 }};
for ( int i = 0; i < queries; i++)
findCount(s, Q[i, 0], Q[i, 1]);
}
}
|
Javascript
<script>
function findCount(s, L, R)
{
var distinct = 0;
var frequency = Array(26).fill(0);
for ( var i = L; i <= R; i++) {
frequency[s[i].charCodeAt(0) - 'a' .charCodeAt(0)]++;
}
for ( var i = 0; i < 26; i++) {
if (frequency[i] > 0)
distinct++;
}
document.write( distinct + "<br>" );
}
var s = "geeksforgeeksisacomputerscienceportal" ;
var queries = 3;
var Q = [ [ 0, 10 ],
[ 15, 18 ],
[ 12, 20 ] ];
for ( var i = 0; i < queries; i++)
findCount(s, Q[i][0], Q[i][1]);
</script>
|
Time Complexity: O(Q×N)
Auxiliary Space: O(26) ? O(1), no extra space is required, so it is a constant.
Efficient Approach: An efficient approach would be to store the position of each character as they appear in the string in an array. For each given query we will iterate over all the 26 lower case alphabets. If the current letter is in the substring S[L: R], then the first element greater than or equal L in the corresponding position vector should exist and be less than or equal to R i.e, there must be a position value between L and R denoting the presence of the alphabet in the query range.
For example:
Below is the implementation of the above approach:
C++
#include <bits/stdc++.h>
using namespace std;
vector<vector< int > > v(26);
void build_position_vector(string s)
{
for ( int i = 0; i < s.size(); i++) {
v[s[i] - 'a' ].push_back(i);
}
}
void findCount(string s, int L, int R)
{
build_position_vector(s);
int distinct = 0;
for ( int i = 0; i < 26; i++) {
auto first = lower_bound(
v[i].begin(),
v[i].end(), L);
if (first != v[i].end()
&& *first <= R) {
distinct++;
}
}
cout << distinct << endl;
}
int main()
{
string s = "geeksforgeeksisacomputerscienceportal" ;
int queries = 3;
int Q[queries][2] = { { 0, 10 },
{ 15, 18 },
{ 12, 20 } };
for ( int i = 0; i < queries; i++)
findCount(s, Q[i][0], Q[i][1]);
return 0;
}
|
Java
import java.util.*;
public class Main {
static ArrayList<ArrayList<Integer>> v = new ArrayList<>( 26 );
static {
for ( int i = 0 ; i < 26 ; i++) {
v.add( new ArrayList<Integer>());
}
}
static void buildPositionVector(String s) {
for ( int i = 0 ; i < s.length(); i++) {
v.get(s.charAt(i) - 'a' ).add(i);
}
}
static void findCount(String s, int L, int R) {
buildPositionVector(s);
int distinct = 0 ;
for ( int i = 0 ; i < 26 ; i++) {
int first = Collections.binarySearch(v.get(i), L);
if (first >= 0 ) {
if (v.get(i).get(first) <= R) {
distinct++;
}
} else {
int insertionPoint = -first - 1 ;
if (insertionPoint < v.get(i).size() && v.get(i).get(insertionPoint) <= R) {
distinct++;
}
}
}
System.out.println(distinct);
}
public static void main(String[] args) {
String s = "geeksforgeeksisacomputerscienceportal" ;
int queries = 3 ;
int [][] Q = { { 0 , 10 },
{ 15 , 18 },
{ 12 , 20 } };
for ( int i = 0 ; i < queries; i++)
findCount(s, Q[i][ 0 ], Q[i][ 1 ]);
}
}
|
Python3
import bisect
v = [[] for i in range ( 26 )]
def build_position_vector(s):
for i in range ( len (s)):
v[ ord (s[i]) - ord ( 'a' )].append(i)
def findCount(s, L, R):
build_position_vector(s)
distinct = 0
for i in range ( 26 ):
first = bisect.bisect_left(v[i], L)
if first < len (v[i]) and v[i][first] < = R:
distinct + = 1
print (distinct)
s = "geeksforgeeksisacomputerscienceportal"
queries = 3
Q = [ [ 0 , 10 ], [ 15 , 18 ], [ 12 , 20 ] ]
for i in range (queries):
findCount(s, Q[i][ 0 ], Q[i][ 1 ])
|
C#
using System;
using System.Collections.Generic;
public class MainClass
{
static List<List< int >> v = new List<List< int >>(26);
static MainClass()
{
for ( int i = 0; i < 26; i++)
{
v.Add( new List< int >());
}
}
static void BuildPositionVector( string s)
{
for ( int i = 0; i < s.Length; i++)
{
v[s[i] - 'a' ].Add(i);
}
}
static void FindCount( string s, int L, int R)
{
BuildPositionVector(s);
int distinct = 0;
for ( int i = 0; i < 26; i++)
{
int first = v[i].BinarySearch(L);
if (first >= 0)
{
if (v[i][first] <= R)
{
distinct++;
}
}
else
{
int insertionPoint = ~first;
if (insertionPoint < v[i].Count && v[i][insertionPoint] <= R)
{
distinct++;
}
}
}
Console.WriteLine(distinct);
}
public static void Main( string [] args)
{
string s = "geeksforgeeksisacomputerscienceportal" ;
int queries = 3;
int [][] Q = { new int [] { 0, 10 },
new int [] { 15, 18 },
new int [] { 12, 20 } };
for ( int i = 0; i < queries; i++)
{
FindCount(s, Q[i][0], Q[i][1]);
}
}
}
|
Javascript
let v = Array(26).fill(0).map(() => []);
function build_position_vector(s) {
for (let i = 0; i < s.length; i++) {
v[s.charCodeAt(i) - 97].push(i);
}
}
function findCount(s, L, R) {
build_position_vector(s);
let distinct = 0;
for (let i = 0; i < 26; i++) {
const first = v[i].find(x => x >= L && x <= R);
if (first !== undefined) {
distinct++;
}
}
console.log(distinct);
}
let s = "geeksforgeeksisacomputerscienceportal" ;
let queries = 3;
let Q = [ [ 0, 10 ],[ 15, 18 ],[ 12, 20 ] ];
for (let i = 0; i < queries; i++)
findCount(s, Q[i][0], Q[i][1]);
|
Time Complexity: O(N + Q logN)
Auxiliary Space: O(N * 26) ? O(N), where N is length of the given string.
Share your thoughts in the comments
Please Login to comment...