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++

filter_none

edit
close

play_arrow

link
brightness_4
code

// CPP program for answering queries to check
// whether a string subsequence or not after
// removing a substring.
#include <bits/stdc++.h>
using namespace std;
  
// arrays to store results of preprocessing
int *fwd, *bwd;
  
// function to preprocess the strings
void preProcess(string a, string b)
{
    int n = a.size();
  
    // Allocate memory for fwd and bwd, and
    // initialize it as 0.
    fwd = new int[n]();
    bwd = new int[n](); 
  
    int j = 0;
  
    // store subsequence count in forward direction
    for (int i = 1; i <= a.size(); i++) {
        if (j < b.size() && a[i - 1] == b[j])
            j++;
  
        // store number of matches till now
        fwd[i] = j;
    }
  
    j = 0;
  
    // store subsequence count in backward direction
    for (int i = a.size(); i >= 1; i--) {
        if (j < b.size() &&
            a[i - 1] == b[b.size() - j - 1])
            j++;
  
        // store number of matches till now
        bwd[i] = j;
    }
}
  
// function that gives the output
void query(string a, string b, int x, int y)
{
    // length of remaining string A is less 
    // than B's length
    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";
}
  
// driver function
int main()
{
    string a = "abcabcxy", b = "acy";
    preProcess(a, b);
  
    // two queries
    int x = 2, y = 5;
    query(a, b, x, y);
  
    x = 3, y = 6;
    query(a, b, x, y);
  
    return 0;
}

chevron_right


Java

filter_none

edit
close

play_arrow

link
brightness_4
code

// Java program for answering 
// queries to check whether 
// a String subsequence or 
// not after removing a substring. 
  
class GFG 
{
    // arrays to store results 
    // of preprocessing 
  
    static int[] fwd = new int[100];
    static int[] bwd = new int[100];
  
    // function to preprocess 
    // the strings 
    static void preProcess(String a,
                            String b) 
    {
        int n = a.length();
  
        // initialize it as 0. 
        int j = 0;
  
        // store subsequence count 
        // in forward direction 
        for (int i = 1;
                i <= a.length(); i++) 
        {
            if (j < b.length() &&
                a.charAt(i - 1) == b.charAt(j))
            {
                j++;
            }
  
            // store number of 
            // matches till now 
            fwd[i] = j;
        }
  
        j = 0;
  
        // store subsequence count 
        // in backward direction 
        for (int i = a.length(); i >= 1; i--) 
        {
            if (j < b.length() && a.charAt(i - 1) ==
                    b.charAt(b.length() - j - 1)) 
            {
                j++;
            }
  
            // store number of 
            // matches till now 
            bwd[i] = j;
        }
    }
  
    // function that gives 
    // the output 
    static void query(String a, String b,
                            int x, int y) 
    {
        // length of remaining 
        // String A is less 
        // than B's length 
        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");
        }
    }
  
    // Driver Code 
    public static void main(String[] args) 
    {
  
        String a = "abcabcxy", b = "acy";
        preProcess(a, b);
  
        // two queries 
        int x = 2, y = 5;
        query(a, b, x, y);
  
        x = 3;
        y = 6;
        query(a, b, x, y);
    }
  
// This code is contributed by 29AjayKumar

chevron_right


Python3

filter_none

edit
close

play_arrow

link
brightness_4
code

# Python3 program for answering
# queries to check whether
# a String subsequence or
# not after removing a substring.
  
# arrays to store results
# of preprocessing
fwd = [0] * 100
bwd = [0] * 100
  
# function to preprocess
# the strings
def preProcess(a, b):
    n = len(a)
  
    # initialize it as 0.
    j = 0
  
    # store subsequence count
    # in forward direction
    for i in range(1, len(a) + 1):
        if j < len(b) and a[i - 1] == b[j]:
            j += 1
  
        # store number of
        # matches till now
        fwd[i] = j
  
    j = 0
  
    # store subsequence count
    # in backward direction
    for i in range(len(a), 0, -1):
        if (j < len(b) and 
            a[i - 1] == b[len(b) - j - 1]):
            j += 1
  
        # store number of
        # matches till now
        bwd[i] = j
  
# function that gives
# the output
def query(a, b, x, y):
  
    # length of remaining
    # String A is less
    # than B's length
    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")
  
# Driver Code
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)
  
# This code is contributed by
# sanjeev2552

chevron_right


C#

filter_none

edit
close

play_arrow

link
brightness_4
code

// C# program for answering 
// queries to check whether 
// a string subsequence or 
// not after removing a substring.
using System;
  
class GFG
{
    // arrays to store results
    // of preprocessing
    static int []fwd = new int[100];
    static int []bwd = new int[100];
      
    // function to preprocess
    // the strings
    static void preProcess(string a, 
                           string b)
    {
        int n = a.Length;
      
        // initialize it as 0.
        int j = 0;
      
        // store subsequence count
        // in forward direction
        for (int i = 1; 
                 i <= a.Length; i++) 
        {
            if (j < b.Length && 
                    a[i - 1] == b[j])
                j++;
      
            // store number of 
            // matches till now
            fwd[i] = j;
        }
      
        j = 0;
      
        // store subsequence count 
        // in backward direction
        for (int i = a.Length;
                 i >= 1; i--) 
        {
            if (j < b.Length &&
                a[i - 1] == b[b.Length - j - 1])
                j++;
      
            // store number of
            // matches till now
            bwd[i] = j;
        }
    }
      
    // function that gives
    // the output
    static void query(string a, string b, 
                      int x, int y)
    {
        // length of remaining 
        // string A is less 
        // than B's length
        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");
    }
      
    // Driver Code
    static void Main()
    {
        string a = "abcabcxy", b = "acy";
        preProcess(a, b);
      
        // two queries
        int x = 2, y = 5;
        query(a, b, x, y);
      
        x = 3; y = 6;
        query(a, b, x, y);
    }
}
  
// This code is contributed by 
// Manish Shaw(manishshaw1)

chevron_right



Output:

Yes
No

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.



My Personal Notes arrow_drop_up

Check out this Author's contributed articles.

If you like GeeksforGeeks and would like to contribute, you can also write an article using contribute.geeksforgeeks.org or mail your article to contribute@geeksforgeeks.org. See your article appearing on the GeeksforGeeks main page and help other Geeks.

Please Improve this article if you find anything incorrect by clicking on the "Improve Article" button below.





Article Tags :
Practice Tags :


Be the First to upvote.


Please write to us at contribute@geeksforgeeks.org to report any issue with the above content.