Given a string P consisting of small English letters and a 26-digit bit string Q, where 1 represents the special character and 0 represents a normal character for the 26 English alphabets. The task is to find the length of the longest substring with at most K normal characters.
Examples:
Input : P = “normal”, Q = “00000000000000000000000000”, K=1
Output : 1
Explanation : In string Q all characters are normal.
Hence, we can select any substring of length 1.
Input : P = “giraffe”, Q = “01111001111111111011111111”, K=2
Output : 3
Explanation : Normal characters in P from Q are {a, f, g, r}.
Therefore, possible substrings with at most 2 normal characters are {gir, ira, ffe}.
The maximum length of all substring is 3.
Approach:
To solve the problem mentioned above we will be using the concept of two pointers. Hence, maintain left and right pointers of the substring, and a count of normal characters. Increment the right index till the count of normal characters is at most K. Then update the answer with a maximum length of substring encountered till now. Increment left index and decrement count till it is greater than K.
Below is the implementation of the above approach:
C++
#include <bits/stdc++.h>
using namespace std;
int maxNormalSubstring(string& P, string& Q,
int K, int N)
{
if (K == 0)
return 0;
int count = 0;
int left = 0, right = 0;
int ans = 0;
while (right < N) {
while (right < N && count <= K) {
int pos = P[right] - 'a' ;
if (Q[pos] == '0' ) {
if (count + 1 > K)
break ;
else
count++;
}
right++;
if (count <= K)
ans = max(ans, right - left);
}
while (left < right) {
int pos = P[left] - 'a' ;
left++;
if (Q[pos] == '0' )
count--;
if (count < K)
break ;
}
}
return ans;
}
int main()
{
string P = "giraffe" , Q = "01111001111111111011111111" ;
int K = 2;
int N = P.length();
cout << maxNormalSubstring(P, Q, K, N);
return 0;
}
|
Java
class GFG{
static int maxNormalSubString( char []P, char []Q,
int K, int N)
{
if (K == 0 )
return 0 ;
int count = 0 ;
int left = 0 , right = 0 ;
int ans = 0 ;
while (right < N) {
while (right < N && count <= K) {
int pos = P[right] - 'a' ;
if (Q[pos] == '0' ) {
if (count + 1 > K)
break ;
else
count++;
}
right++;
if (count <= K)
ans = Math.max(ans, right - left);
}
while (left < right) {
int pos = P[left] - 'a' ;
left++;
if (Q[pos] == '0' )
count--;
if (count < K)
break ;
}
}
return ans;
}
public static void main(String[] args)
{
String P = "giraffe" , Q = "01111001111111111011111111" ;
int K = 2 ;
int N = P.length();
System.out.print(maxNormalSubString(P.toCharArray(), Q.toCharArray(), K, N));
}
}
|
Python3
def maxNormalSubstring(P, Q, K, N):
if (K = = 0 ):
return 0
count = 0
left, right = 0 , 0
ans = 0
while (right < N):
while (right < N and count < = K):
pos = ord (P[right]) - ord ( 'a' )
if (Q[pos] = = '0' ):
if (count + 1 > K):
break
else :
count + = 1
right + = 1
if (count < = K):
ans = max (ans, right - left)
while (left < right):
pos = ord (P[left]) - ord ( 'a' )
left + = 1
if (Q[pos] = = '0' ):
count - = 1
if (count < K):
break
return ans
if (__name__ = = "__main__" ):
P = "giraffe"
Q = "01111001111111111011111111"
K = 2
N = len (P)
print (maxNormalSubstring(P, Q, K, N))
|
C#
using System;
public class GFG{
static int maxNormalSubString( char []P, char []Q,
int K, int N)
{
if (K == 0)
return 0;
int count = 0;
int left = 0, right = 0;
int ans = 0;
while (right < N) {
while (right < N && count <= K) {
int pos = P[right] - 'a' ;
if (Q[pos] == '0' ) {
if (count + 1 > K)
break ;
else
count++;
}
right++;
if (count <= K)
ans = Math.Max(ans, right - left);
}
while (left < right) {
int pos = P[left] - 'a' ;
left++;
if (Q[pos] == '0' )
count--;
if (count < K)
break ;
}
}
return ans;
}
public static void Main(String[] args)
{
String P = "giraffe" , Q = "01111001111111111011111111" ;
int K = 2;
int N = P.Length;
Console.Write(maxNormalSubString(P.ToCharArray(),
Q.ToCharArray(), K, N));
}
}
|
Javascript
<script>
function maxNormalSubstring(P, Q, K, N)
{
if (K == 0)
return 0;
var count = 0;
var left = 0, right = 0;
var ans = 0;
while (right < N) {
while (right < N && count <= K) {
var pos = P[right].charCodeAt(0) - 'a' .charCodeAt(0);
if (Q[pos] == '0' ) {
if (count + 1 > K)
break ;
else
count++;
}
right++;
if (count <= K)
ans = Math.max(ans, right - left);
}
while (left < right) {
var pos = P[left].charCodeAt(0) - 'a' .charCodeAt(0);
left++;
if (Q[pos] == '0' )
count--;
if (count < K)
break ;
}
}
return ans;
}
var P = "giraffe" , Q = "01111001111111111011111111" ;
var K = 2;
var N = P.length;
document.write( maxNormalSubstring(P, Q, K, N));
</script>
|
Time Complexity: O(N*N)
Auxiliary Space: O(1)
Another Approach:
Initialize two variables, start and end, to zero, a variable max_len to zero, and an array freq of size 26 to zero.
Traverse the string from left to right:
a. Increment the frequency of the current character in the freq array.
b. If the frequency of the current character exceeds k, move the start pointer to the right and decrement the frequency of the character at the previous start position.
c. Update the max_len if the current substring length is greater than max_len.
Return max_len.
C++
#include <iostream>
#include <string.h>
using namespace std;
int main() {
char str[] = "aabbccddd" ;
int k = 2;
int n = strlen (str);
int start = 0;
int end = 0;
int max_len = 0;
int freq[26] = {0};
while (end < n) {
freq[str[end] - 'a' ]++;
if (freq[str[end] - 'a' ] > k) {
freq[str[start] - 'a' ]--;
start++;
}
max_len = (end - start + 1 > max_len) ? end - start + 1 : max_len;
end++;
}
cout << "Length of longest substring with at most " << k << " normal characters is: " << max_len << endl;
return 0;
}
|
C
#include <stdio.h>
#include <string.h>
int main() {
char str[] = "aabbccddd" ;
int k = 2;
int n = strlen (str);
int start = 0;
int end = 0;
int max_len = 0;
int freq[26] = {0};
while (end < n) {
freq[str[end] - 'a' ]++;
if (freq[str[end] - 'a' ] > k) {
freq[str[start] - 'a' ]--;
start++;
}
max_len = (end - start + 1 > max_len) ? end - start + 1 : max_len;
end++;
}
printf ( "Length of longest substring with at most %d normal characters is: %d\n" , k, max_len);
return 0;
}
|
Java
import java.util.*;
public class Main {
public static void main(String[] args) {
String str = "aabbccddd" ;
int k = 2 ;
int n = str.length();
int start = 0 ;
int end = 0 ;
int max_len = 0 ;
int [] freq = new int [ 26 ];
while (end < n) {
freq[str.charAt(end) - 'a' ]++;
if (freq[str.charAt(end) - 'a' ] > k) {
freq[str.charAt(start) - 'a' ]--;
start++;
}
max_len = (end - start + 1 > max_len) ? end - start + 1 : max_len;
end++;
}
System.out.printf( "Length of longest substring with at most %d normal characters is: %d\n" , k, max_len);
}
}
|
Python3
def longest_substring( str , k):
n = len ( str )
start = 0
end = 0
max_len = 0
freq = [ 0 ] * 26
while end < n:
freq[ ord ( str [end]) - ord ( 'a' )] + = 1
if freq[ ord ( str [end]) - ord ( 'a' )] > k:
freq[ ord ( str [start]) - ord ( 'a' )] - = 1
start + = 1
max_len = max (max_len, end - start + 1 )
end + = 1
print ( "Length of longest substring with at most" , k, "normal characters is:" , max_len)
str = "aabbccddd"
k = 2
longest_substring( str , k)
|
C#
using System;
class MainClass {
public static void Main ( string [] args) {
char [] str = "aabbccddd" .ToCharArray();
int k = 2;
int n = str.Length;
int start = 0;
int end = 0;
int max_len = 0;
int [] freq = new int [26];
while (end < n) {
freq[str[end] - 'a' ]++;
if (freq[str[end] - 'a' ] > k) {
freq[str[start] - 'a' ]--;
start++;
}
max_len = (end - start + 1 > max_len) ? end - start + 1 : max_len;
end++;
}
Console.WriteLine( "Length of longest substring with at most {0} normal characters is: {1}" , k, max_len);
}
}
|
Javascript
function findLongestSubstring(str, k) {
const n = str.length;
let start = 0;
let end = 0;
let max_len = 0;
let freq = new Array(26).fill(0);
while (end < n) {
freq[str.charCodeAt(end) - 'a' .charCodeAt()]++;
if (freq[str.charCodeAt(end) - 'a' .charCodeAt()] > k) {
freq[str.charCodeAt(start) - 'a' .charCodeAt()]--;
start++;
}
max_len = Math.max(end - start + 1, max_len);
end++;
}
return max_len;
}
const str = "aabbccddd" ;
const k = 2;
const longestSubstringLength = findLongestSubstring(str, k);
console.log(`Length of longest substring with at most ${k} normal characters is: ${longestSubstringLength}`);
|
OutputLength of longest substring with at most 2 normal characters is: 8
time complexity of O(n), where n is the string length
space complexity of O(1)