Check if it is possible to form string B from A under the given constraints
Last Updated :
09 Feb, 2023
Given two strings A and B and two integers b and m. The task is to find that if it is possible to form string B from A such that A is divided into groups of b characters except the last group which will have characters ? b and you are allowed to pick atmost m characters from each group, and also order of characters in B must be same as that of A. If it is possible then print Yes else print No.
Examples:
Input: A = abcbbcdefxyz, B = acdxyz, b = 5, m = 2
Output: Yes
Groups can be "abcbb", "cdefx" and "yz"
Now "acdxyz" can be used to pick "ac" and "dx" can be picked from "cdefx".
Finally, "yz" if the last group.
Input: A = abcbbcdefxyz, B = baz, b = 3, m = 2
Output: No
Approach: The idea is to use binary search. Iterate through string A and store the frequency of each of the characters of A in vector S. Now iterate through B and if the current character is not in the vector then print No since its not possible to form string B using A. Else, check the first occurrence of current character starting from the index of the last chosen character low, which denotes starting position in string A from where we want to match characters of string B. Keep track of number of characters stored in each group. If it exceeds, the given limit of characters in current block, we update the pointer low to the next block.
Below is the implementation of the above approach:
C++
// C++ implementation of the approach
#include <bits/stdc++.h>
using namespace std;
// Function that returns true if it is possible
// to form B from A satisfying the given conditions
bool isPossible(string A, string B, int b, int m)
{
// Vector to store the frequency
// of characters in A
vector<int> S[26];
// Vector to store the count of characters
// used from a particular group of characters
vector<int> box(A.length(), 0);
// Store the frequency of the characters
for (int i = 0; i < A.length(); i++) {
S[A[i] - 'a'].push_back(i);
}
int low = 0;
for (int i = 0; i < B.length(); i++) {
auto it = lower_bound(S[B[i] - 'a'].begin(),
S[B[i] - 'a'].end(), low);
// If a character in B is not
// present in A
if (it == S[B[i] - 'a'].end())
return false;
int count = (*it) / b;
box[count] = box[count] + 1;
// If count of characters used from
// a particular group of characters
// exceeds m
if (box[count] >= m) {
count++;
// Update low to the starting index
// of the next group
low = (count)*b;
}
// If count of characters used from
// a particular group of characters
// has not exceeded m
else
low = (*it) + 1;
}
return true;
}
// Driver code
int main()
{
string A = "abcbbcdefxyz";
string B = "acdxyz";
int b = 5;
int m = 2;
if (isPossible(A, B, b, m))
cout << "Yes";
else
cout << "No";
return 0;
}
Java
// Java implementation of the approach
import java.io.*;
import java.util.*;
class GFG{
// Function that returns true if it is
// possible to form B from A satisfying
// the given conditions
static boolean isPossible(String A, String B,
int b, int m)
{
// List to store the frequency
// of characters in A
List<List<Integer>> S = new ArrayList<List<Integer>>();
for(int i = 0; i < 26; i++)
S.add(new ArrayList<Integer>());
// Vector to store the count of characters
// used from a particular group of characters
int[] box = new int[A.length()];
// Store the frequency of the characters
for(int i = 0; i < A.length(); i++)
{
S.get(A.charAt(i) - 'a').add(i);
}
int low = 0;
for(int i = 0; i < B.length(); i++)
{
List<Integer> indexes = S.get(
B.charAt(i) - 'a');
int it = lower_bound(indexes, low);
// If a character in B is not
// present in A
if (it == indexes.size())
return false;
int count = indexes.get(it) / b;
box[count] = box[count] + 1;
// If count of characters used from
// a particular group of characters
// exceeds m
if (box[count] >= m)
{
count++;
// Update low to the starting index
// of the next group
low = (count) * b;
}
// If count of characters used from
// a particular group of characters
// has not exceeded m
else
low = indexes.get(it) + 1;
}
return true;
}
static int lower_bound(List<Integer> indexes, int k)
{
int low = 0, high = indexes.size() - 1;
while (low < high)
{
int mid = (low + high) / 2;
if (indexes.get(mid) < k)
low = mid + 1;
else
high = mid;
}
return (indexes.get(low) < k) ? low + 1 : low;
}
// Driver code
public static void main(String[] args)
{
String A = "abcbbcdefxyz";
String B = "acdxyz";
int b = 5;
int m = 2;
if (isPossible(A, B, b, m))
System.out.println("Yes");
else
System.out.println("No");
}
}
// This code is contributed by jithin
Python3
# Python3 implementation of the approach
# Function that returns true if it is
# possible to form B from A satisfying
# the given conditions
def isPossible(A, B, b, m) :
# List to store the frequency
# of characters in A
S = []
for i in range(26) :
S.append([])
# Vector to store the count of characters
# used from a particular group of characters
box = [0] * len(A)
# Store the frequency of the characters
for i in range(len(A)) :
S[ord(A[i]) - ord('a')].append(i)
low = 0
for i in range(len(B)) :
indexes = S[ord(B[i]) - ord('a')]
it = lower_bound(indexes, low)
# If a character in B is not
# present in A
if (it == len(indexes)) :
return False
count = indexes[it] // b
box[count] = box[count] + 1
# If count of characters used from
# a particular group of characters
# exceeds m
if (box[count] >= m) :
count += 1
# Update low to the starting index
# of the next group
low = (count) * b
# If count of characters used from
# a particular group of characters
# has not exceeded m
else :
low = indexes[it] + 1
return True
def lower_bound(indexes, k) :
low, high = 0, len(indexes) - 1
while (low < high) :
mid = (low + high) // 2
if (indexes[mid] < k) :
low = mid + 1
else :
high = mid
if indexes[low] < k :
return (low + 1)
else :
return low
A = "abcbbcdefxyz"
B = "acdxyz"
b = 5
m = 2
if (isPossible(A, B, b, m)) :
print("Yes")
else :
print("No")
# This code is contributed by divyeshrabadiya07
C#
// C# implementation of the approach
using System;
using System.Collections.Generic;
class GFG {
// Function that returns true if it is
// possible to form B from A satisfying
// the given conditions
static bool isPossible(string A, string B, int b, int m)
{
// List to store the frequency
// of characters in A
List<List<int>> S = new List<List<int>>();
for(int i = 0; i < 26; i++)
{
S.Add(new List<int>());
}
// Vector to store the count of characters
// used from a particular group of characters
int[] box = new int[A.Length];
// Store the frequency of the characters
for(int i = 0; i < A.Length; i++)
{
S[A[i] - 'a'].Add(i);
}
int low = 0;
for(int i = 0; i < B.Length; i++)
{
List<int> indexes = S[B[i] - 'a'];
int it = lower_bound(indexes, low);
// If a character in B is not
// present in A
if (it == indexes.Count)
return false;
int count = indexes[it] / b;
box[count] = box[count] + 1;
// If count of characters used from
// a particular group of characters
// exceeds m
if (box[count] >= m)
{
count++;
// Update low to the starting index
// of the next group
low = (count) * b;
}
// If count of characters used from
// a particular group of characters
// has not exceeded m
else
low = indexes[it] + 1;
}
return true;
}
static int lower_bound(List<int> indexes, int k)
{
int low = 0, high = indexes.Count - 1;
while (low < high)
{
int mid = (low + high) / 2;
if (indexes[mid] < k)
low = mid + 1;
else
high = mid;
}
return (indexes[low] < k) ? low + 1 : low;
}
static void Main() {
string A = "abcbbcdefxyz";
string B = "acdxyz";
int b = 5;
int m = 2;
if (isPossible(A, B, b, m))
Console.WriteLine("Yes");
else
Console.WriteLine("No");
}
}
// This code is contributed by divyesh072019
JavaScript
// Function that returns true if it is
// possible to form B from A satisfying
// the given conditions
const isPossible = (A, B, b, m) => {
const S = [];
// List to store the frequency
// of characters in A
for (let i = 0; i < 26; i++) {
S.push([]);
}
// Vector to store the count of characters
// used from a particular group of characters
const box = new Array(A.length).fill(0);
// Store the frequency of the characters
for (let i = 0; i < A.length; i++) {
S[A.charCodeAt(i) - 'a'.charCodeAt(0)].push(i);
}
let low = 0;
for (let i = 0; i < B.length; i++) {
const indexes = S[B.charCodeAt(i) - 'a'.charCodeAt(0)];
let it = lower_bound(indexes, low);
// If a character in B is not
// present in A
if (it === indexes.length) {
return false;
}
let count = Math.floor(indexes[it] / b);
box[count] = box[count] + 1;
// If count of characters used from
// a particular group of characters
// exceeds m
if (box[count] >= m)
{
// Update low to the starting index
// of the next group
count++;
low = count * b;
}
// If count of characters used from
// a particular group of characters
// has not exceeded m
else {
low = indexes[it] + 1;
}
}
return true;
};
const lower_bound = (indexes, k) => {
let low = 0;
let high = indexes.length - 1;
while (low < high) {
const mid = Math.floor((low + high) / 2);
if (indexes[mid] < k) {
low = mid + 1;
} else {
high = mid;
}
}
return indexes[low] < k ? low + 1 : low;
};
const A = 'abcbbcdefxyz';
const B = 'acdxyz';
const b = 5;
const m = 2;
console.log(isPossible(A, B, b, m) ? 'Yes' : 'No');
Similar Reads
Check if it is possible to convert one string into another with given constraints Given two strings contains three characters i.e 'A', 'B 'and '#' only. Check is it possible to convert first string into another string by performing following operations on string first. 'A' can move towards Left only 'B' can move towards Right only Neither 'A' nor 'B' cross each other If it is pos
8 min read
Count of strings that can be formed using a, b and c under given constraints Given a length n, count the number of strings of length n that can be made using 'a', 'b' and 'c' with at most one 'b' and two 'c's allowed. Examples : Input : n = 3 Output : 19 Below strings follow given constraints: aaa aab aac aba abc aca acb acc baa bac bca bcc caa cab cac cba cbc cca ccb Input
14 min read
Check if it is possible to make all strings of A[] equal to B[] using given operations Consider two arrays, A[] and B[], each containing N strings. These strings are composed solely of digits ranging from 0 to 9. Then your task is to output YES or NO, by following that all the strings of A[] can be made equal to B[] for each i (1 <= i <= N) in at most K cost. The following opera
9 min read
Check if 2 * K + 1 non-empty strings exists whose concatenation forms the given string Given a string S consisting of N characters and positive integer K, the task is to check if there exist any (K + 1) strings i.e., A1, A2, A3, ..., AK, A(K + 1) such that the concatenation of strings A1, A2, A3, ..., AK, and A(K + 1) and the concatenation of the reverse of each strings AK, A(K - 1),
6 min read
Check if it is possible to transform one string to another Given two strings s1 and s2(all letters in uppercase). Check if it is possible to convert s1 to s2 by performing following operations. Make some lowercase letters uppercase. Delete all the lowercase letters. Examples: Input : s1 = daBcd s2 = ABC Output : yes Explanation : daBcd -> dABCd -> ABC
7 min read