Subsequence queries after removing substrings
Given two strings A and B, the problem is to find if string B will be a subsequence of string A if we remove the substring [A[i]..A[j]] from string A. Assume that there are Q queries giving the indices i and j and each query is independent of the other.
Examples:
Input : A = abcabcxy, B = acy
Q = 2
i = 2, j = 5
i = 3, j = 6
Output :
Yes
No
Explanation :
In the first query we remove A[2]..A[5],
getting acxy and acy is its subsequence.
In the second query we remove A[3]..A[6],
getting abxy but acy is not its subsequence.
A brute force approach is, for each query remove the required substring from A and check if B is a subsequence of A, but is inefficient because we have to modify the string A for each query and also check if string B is its subsequence.
A more efficient approach is to do preprocessing on the strings as we have to encounter multiple queries. We can store the number of characters of string B that matches till each index of string A in both the forward and backward directions, in two separate arrays. Finally we can say the answer is Yes, if the following equation holds, otherwise No:
forward[i-1] + backward[j+1] >= length(B).
This works because we are removing A[i]..A[j] from A and want to know the sum of number of characters of B that match in A
from A[1]..A[i-1] and A[j+1]..A[len], which is a subsequence if this sum is atleast the length of string B.
Following is the implementation of the above approach:
C++
#include <bits/stdc++.h>
using namespace std;
int *fwd, *bwd;
void preProcess(string a, string b)
{
int n = a.size();
fwd = new int [n]();
bwd = new int [n]();
int j = 0;
for ( int i = 1; i <= a.size(); i++) {
if (j < b.size() && a[i - 1] == b[j])
j++;
fwd[i] = j;
}
j = 0;
for ( int i = a.size(); i >= 1; i--) {
if (j < b.size() &&
a[i - 1] == b[b.size() - j - 1])
j++;
bwd[i] = j;
}
}
void query(string a, string b, int x, int y)
{
if ((x - 1 + a.size() - y) < b.size()) {
cout << "No\n" ;
return ;
}
if (fwd[x - 1] + bwd[y + 1] >= b.size())
cout << "Yes\n" ;
else
cout << "No\n" ;
}
int main()
{
string a = "abcabcxy" , b = "acy" ;
preProcess(a, b);
int x = 2, y = 5;
query(a, b, x, y);
x = 3, y = 6;
query(a, b, x, y);
return 0;
}
|
Java
class GFG
{
static int [] fwd = new int [ 100 ];
static int [] bwd = new int [ 100 ];
static void preProcess(String a,
String b)
{
int n = a.length();
int j = 0 ;
for ( int i = 1 ;
i <= a.length(); i++)
{
if (j < b.length() &&
a.charAt(i - 1 ) == b.charAt(j))
{
j++;
}
fwd[i] = j;
}
j = 0 ;
for ( int i = a.length(); i >= 1 ; i--)
{
if (j < b.length() && a.charAt(i - 1 ) ==
b.charAt(b.length() - j - 1 ))
{
j++;
}
bwd[i] = j;
}
}
static void query(String a, String b,
int x, int y)
{
if ((x - 1 + a.length() - y) < b.length())
{
System.out.print( "No\n" );
return ;
}
if (fwd[x - 1 ] + bwd[y + 1 ] >= b.length())
{
System.out.print( "Yes\n" );
}
else
{
System.out.print( "No\n" );
}
}
public static void main(String[] args)
{
String a = "abcabcxy" , b = "acy" ;
preProcess(a, b);
int x = 2 , y = 5 ;
query(a, b, x, y);
x = 3 ;
y = 6 ;
query(a, b, x, y);
}
}
|
Python3
fwd = [ 0 ] * 100
bwd = [ 0 ] * 100
def preProcess(a, b):
n = len (a)
j = 0
for i in range ( 1 , len (a) + 1 ):
if j < len (b) and a[i - 1 ] = = b[j]:
j + = 1
fwd[i] = j
j = 0
for i in range ( len (a), 0 , - 1 ):
if (j < len (b) and
a[i - 1 ] = = b[ len (b) - j - 1 ]):
j + = 1
bwd[i] = j
def query(a, b, x, y):
if (x - 1 + len (a) - y) < len (b):
print ( "No" )
return
if (fwd[x - 1 ] + bwd[y + 1 ]) > = len (b):
print ( "Yes" )
else :
print ( "No" )
if __name__ = = "__main__" :
a = "abcabcxy"
b = "acy"
preProcess(a, b)
x = 2
y = 5
query(a, b, x, y)
x = 3
y = 6
query(a, b, x, y)
|
C#
using System;
class GFG
{
static int []fwd = new int [100];
static int []bwd = new int [100];
static void preProcess( string a,
string b)
{
int n = a.Length;
int j = 0;
for ( int i = 1;
i <= a.Length; i++)
{
if (j < b.Length &&
a[i - 1] == b[j])
j++;
fwd[i] = j;
}
j = 0;
for ( int i = a.Length;
i >= 1; i--)
{
if (j < b.Length &&
a[i - 1] == b[b.Length - j - 1])
j++;
bwd[i] = j;
}
}
static void query( string a, string b,
int x, int y)
{
if ((x - 1 + a.Length - y) < b.Length)
{
Console.Write( "No\n" );
return ;
}
if (fwd[x - 1] +
bwd[y + 1] >= b.Length)
Console.Write( "Yes\n" );
else
Console.Write( "No\n" );
}
static void Main()
{
string a = "abcabcxy" , b = "acy" ;
preProcess(a, b);
int x = 2, y = 5;
query(a, b, x, y);
x = 3; y = 6;
query(a, b, x, y);
}
}
|
Javascript
<script>
let fwd = new Array(100);
let bwd = new Array(100);
function preProcess(a,b)
{
let n = a.length;
let j = 0;
for (let i = 1;
i <= a.length; i++)
{
if (j < b.length &&
a[i - 1] == b[j])
{
j++;
}
fwd[i] = j;
}
j = 0;
for (let i = a.length; i >= 1; i--)
{
if (j < b.length && a[i-1] ==
b[b.length - j - 1])
{
j++;
}
bwd[i] = j;
}
}
function query(a,b,x,y)
{
if ((x - 1 + a.length - y) < b.length)
{
document.write( "No<br>" );
return ;
}
if (fwd[x - 1] + bwd[y + 1] >= b.length)
{
document.write( "Yes<br>" );
}
else
{
document.write( "No<br>" );
}
}
let a = "abcabcxy" , b = "acy" ;
preProcess(a, b);
let x = 2, y = 5;
query(a, b, x, y);
x = 3;
y = 6;
query(a, b, x, y);
</script>
|
The time complexity of the above approach is O(n + q), where q is the number of queries and n is the length of string A.
Auxiliary Space: O(n)
Last Updated :
27 Apr, 2023
Like Article
Save Article
Share your thoughts in the comments
Please Login to comment...