Queries to check if string B exists as substring in string A - GeeksforGeeks

15 Nov, 2021
Given two strings A, B and some queries consisting of an integer i, the task is to check whether the sub-string of A starting from index i and ending at index i + length(B) – 1 equals B or not. If equal then print Yes else print No. Note that i + length(B) will always be smaller than length(A).
Examples: 
Input: A = “abababa”, B = “aba”, q[] = {0, 1, 2, 3} Output: Yes No Yes No a[0-2] = “aba” = b (both are equal) a[1-3] = “bab” != b a[2-4] = “aba” = b a[3-5] = “bab” !=b
Input: A = “GeeksForGeeks”, B = “Geeks”, q[] = {0, 5, 8} Output: Yes No Yes  
A simple approach will be to compare the strings character by character for every query which will take O(length(B)) time to answer each query.
Efficient approach: We will optimize the query processing using rolling hash algorithm. First, we will find hash value of string B. Then, using rolling hash technique, we will do the pre-processing of string A. Let’s suppose we created an array hash_A. Then ith element of this array will store. 
((a[0] – 97) + (a[1] – 97) * d + (a[2] – 97) * d2 + ..... + (a[i] – 97) * di) % mod where d is the multiplier in rolling-hash. 
We will use this to find hash of the sub-string of A. 
Hash of sub-string of A starting from i can be found as (hash_a[i + len_b – 1] – hash_a[i – 1]) / di or more specifically 
((hash_a[i + len_b – 1] – hash_a[i – 1] + 2 * mod) * mi(di)) % mod 
Thus, using this we can answer each query in O(1).
Below is the implementation of the above approach: 
C++
Java
Python3
C#
Javascript
// C++ implementation of the approach#include <bits/stdc++.h>#define mod 3803#define d 26using namespace std; int hash_b;int* hash_a;int* mul; // Function to return the modular inverse// using Fermat's little theoremint mi(int x){    int p = mod - 2;    int s = 1;    while (p != 1) {        if (p % 2 == 1)            s = (s * x) % mod;        x = (x * x) % mod;        p /= 2;    }     return (s * x) % mod;} // Function to generate hashvoid genHash(string& a, string& b){    // To store prefix-sum    // of rolling hash    hash_a = new int[a.size()];     // Multiplier for different values of i    mul = new int[a.size()];     // Generating hash value for string b    for (int i = b.size() - 1; i >= 0; i--)        hash_b = (hash_b * d + (b[i] - 97)) % mod;     // Generating prefix-sum of hash of a    mul[0] = 1;    hash_a[0] = (a[0] - 97) % mod;    for (int i = 1; i < a.size(); i++) {        mul[i] = (mul[i - 1] * d) % mod;        hash_a[i]            = (hash_a[i - 1] + mul[i] * (a[i] - 97)) % mod;    }} // Function that returns true if the// required sub-string in a is equal to bbool checkEqual(int i, int len_a, int len_b){    // To store hash of required    // sub-string of A    int x;     // If i = 0 then    // requires hash value    if (i == 0)        x = hash_a[len_b - 1];     // Required hash if i != 0    else {        x = (hash_a[i + len_b - 1] - hash_a[i - 1]             + 2 * mod)            % mod;        x = (x * mi(mul[i])) % mod;    }     // Comparing hash with hash of B    if (x == hash_b)        return true;     return false;} // Driver codeint main(){    string a = "abababababa";    string b = "aba";     // Generating hash    genHash(a, b);     // Queries    int queries[] = { 0, 1, 2, 3 };    int q = sizeof(queries) / sizeof(queries[0]);     // Perform queries    for (int i = 0; i < q; i++) {        if (checkEqual(queries[i], a.size(), b.size()))            cout << "Yes\n";        else            cout << "No\n";    }     return 0;}
// Java implementation of the approachimport java.util.*; class GFG {     static int mod = 3803;    static int d = 26;     static int hash_b;    static int[] hash_a;    static int[] mul;     // Function to return the modular inverse    // using Fermat's little theorem    static int mi(int x)    {        int p = mod - 2;        int s = 1;        while (p != 1) {            if (p % 2 == 1) {                s = (s * x) % mod;            }            x = (x * x) % mod;            p /= 2;        }         return (s * x) % mod;    }     // Function to generate hash    static void genHash(char[] a, char[] b)    {        // To store prefix-sum        // of rolling hash        hash_a = new int[a.length];         // Multiplier for different values of i        mul = new int[a.length];         // Generating hash value for string b        for (int i = b.length - 1; i >= 0; i--) {            hash_b = (hash_b * d + (b[i] - 97)) % mod;        }         // Generating prefix-sum of hash of a        mul[0] = 1;        hash_a[0] = (a[0] - 97) % mod;        for (int i = 1; i < a.length; i++) {            mul[i] = (mul[i - 1] * d) % mod;            hash_a[i]                = (hash_a[i - 1] + mul[i] * (a[i] - 97))                  % mod;        }    }     // Function that returns true if the    // required sub-string in a is equal to b    static boolean checkEqual(int i, int len_a, int len_b)    {        // To store hash of required        // sub-string of A        int x;         // If i = 0 then        // requires hash value        if (i == 0) {            x = hash_a[len_b - 1];        }        // Required hash if i != 0        else {            x = (hash_a[i + len_b - 1] - hash_a[i - 1]                 + 2 * mod)                % mod;            x = (x * mi(mul[i])) % mod;        }         // Comparing hash with hash of B        if (x == hash_b) {            return true;        }         return false;    }     // Driver code    public static void main(String[] args)    {        String a = "abababababa";        String b = "aba";         // Generating hash        genHash(a.toCharArray(), b.toCharArray());         // Queries        int queries[] = { 0, 1, 2, 3 };        int q = queries.length;         // Perform queries        for (int i = 0; i < q; i++) {            if (checkEqual(queries[i], a.length(),                           b.length())) {                System.out.println("Yes");            }            else {                System.out.println("No");            }        }    }} /* This code is contributed by PrinciRaj1992 */
# Python3 implementation of the approachmod = 3803d = 26 hash_b = 0hash_a = []mul = [] # Function to return the modular inverse# using Fermat's little theorem  def mi(x):    global mod    p = mod - 2    s = 1    while p != 1:        if p % 2 == 1:            s = (s * x) % mod         x = (x * x) % mod        p //= 2     return (s * x) % mod # Function to generate hash  def genHash(a, b):    global hash_b, hash_a, mul, d, mod     # To store prefix-sum    # of rolling hash    hash_a = [0] * len(a)     # Multiplier for different values of i    mul = [0] * len(a)     # Generating hash value for string b    for i in range(len(b) - 1, -1, -1):        hash_b = (hash_b * d +                  (ord(b[i]) - 97)) % mod     # Generating prefix-sum of hash of a    mul[0] = 1    hash_a[0] = (ord(a[0]) - 97) % mod    for i in range(1, len(a)):        mul[i] = (mul[i - 1] * d) % mod        hash_a[i] = (hash_a[i - 1] + mul[i] *                     (ord(a[i]) - 97)) % mod # Function that returns true if the# required sub-string in a is equal to b  def checkEqual(i, len_a, len_b):    global hash_b, hash_a, mul, d, mod     # To store hash of required    # sub-string of A    x = -1     # If i = 0 then    # requires hash value    if i == 0:        x = hash_a[len_b - 1]     # Required hash if i != 0    else:        x = (hash_a[i + len_b - 1] -             hash_a[i - 1] + 2 * mod) % mod        x = (x * mi(mul[i])) % mod     # Comparing hash with hash of B    if x == hash_b:        return True     return False  # Driver Codeif __name__ == "__main__":    a = "abababababa"    b = "aba"     # Generating hash    genHash(a, b)     # Queries    queries = [0, 1, 2, 3]    q = len(queries)     # Perform queries    for i in range(q):        if checkEqual(queries[i], len(a), len(b)):            print("Yes")        else:            print("No") # This code is contributed by# sanjeev2552
// C# implementation of the approachusing System; class GFG {     static int mod = 3803;    static int d = 26;     static int hash_b;    static int[] hash_a;    static int[] mul;     // Function to return the modular inverse    // using Fermat's little theorem    static int mi(int x)    {        int p = mod - 2;        int s = 1;        while (p != 1) {            if (p % 2 == 1) {                s = (s * x) % mod;            }            x = (x * x) % mod;            p /= 2;        }         return (s * x) % mod;    }     // Function to generate hash    static void genHash(char[] a, char[] b)    {        // To store prefix-sum        // of rolling hash        hash_a = new int[a.Length];         // Multiplier for different values of i        mul = new int[a.Length];         // Generating hash value for string b        for (int i = b.Length - 1; i >= 0; i--) {            hash_b = (hash_b * d + (b[i] - 97)) % mod;        }         // Generating prefix-sum of hash of a        mul[0] = 1;        hash_a[0] = (a[0] - 97) % mod;        for (int i = 1; i < a.Length; i++) {            mul[i] = (mul[i - 1] * d) % mod;            hash_a[i]                = (hash_a[i - 1] + mul[i] * (a[i] - 97))                  % mod;        }    }     // Function that returns true if the    // required sub-string in a is equal to b    static Boolean checkEqual(int i, int len_a, int len_b)    {        // To store hash of required        // sub-string of A        int x;         // If i = 0 then        // requires hash value        if (i == 0) {            x = hash_a[len_b - 1];        }        // Required hash if i != 0        else {            x = (hash_a[i + len_b - 1] - hash_a[i - 1]                 + 2 * mod)                % mod;            x = (x * mi(mul[i])) % mod;        }         // Comparing hash with hash of B        if (x == hash_b) {            return true;        }         return false;    }     // Driver code    public static void Main(String[] args)    {        String a = "abababababa";        String b = "aba";         // Generating hash        genHash(a.ToCharArray(), b.ToCharArray());         // Queries        int[] queries = { 0, 1, 2, 3 };        int q = queries.Length;         // Perform queries        for (int i = 0; i < q; i++) {            if (checkEqual(queries[i], a.Length,                           b.Length)) {                Console.WriteLine("Yes");            }            else {                Console.WriteLine("No");            }        }    }} /* This code contributed by PrinciRaj1992 */
<script> // Javascript implementation of the approachvar mod = 3803;var d = 26; var hash_b = 0;var hash_a = [];var mul = []; // Function to return the modular inverse// using Fermat's little theoremfunction mi(x){    var p = mod - 2;    var s = 1;    while (p != 1) {        if (p % 2 == 1)            s = (s * x) % mod;        x = (x * x) % mod;        p = parseInt(p/2);    }     return (s * x) % mod;} // Function to generate hashfunction genHash(a, b){    // To store prefix-sum    // of rolling hash    hash_a = Array(a.length).fill(0);     // Multiplier for different values of i    mul = Array(a.length).fill(0);     // Generating hash value for string b    for (var i = b.length - 1; i >= 0; i--)        hash_b = (hash_b * d + (b[i].charCodeAt(0) - 97)) % mod;     // Generating prefix-sum of hash of a    mul[0] = 1;    hash_a[0] = (a[0].charCodeAt(0) - 97) % mod;    for (var i = 1; i < a.length; i++) {        mul[i] = (mul[i - 1] * d) % mod;        hash_a[i]            = (hash_a[i - 1] + mul[i] * (a[i].charCodeAt(0) - 97)) % mod;    }} // Function that returns true if the// required sub-string in a is equal to bfunction checkEqual(i, len_a, len_b){    // To store hash of required    // sub-string of A    var x;     // If i = 0 then    // requires hash value    if (i == 0)        x = hash_a[len_b - 1];     // Required hash if i != 0    else {        x = (hash_a[i + len_b - 1] - hash_a[i - 1]             + 2 * mod)            % mod;        x = (x * mi(mul[i])) % mod;    }     // Comparing hash with hash of B    if (x == hash_b)        return true;     return false;} // Driver codevar a = "abababababa";var b = "aba"; // Generating hashgenHash(a.split(''), b.split('')); // Queriesvar queries = [0, 1, 2, 3];var q = queries.length // Perform queriesfor (var i = 0; i < q; i++) {    if (checkEqual(queries[i], a.length, b.length))        document.write("Yes<br>");    else    document.write("No<br>");} // This code is contributed by rrrtnx.</script>
Yes
No
Yes
No
Note: For simplicity, we have used only one hash function. Use double/triple hash to eliminate any chance of collision and more accurate result.
The above question can be solved by using DP also, below is the java code.
Java
C#
Javascript
import java.io.*;import java.util.*;import java.lang.*;import java.io.*; public class GFG{    private static void    substringCheck(String stra, String strb, int[] query)    {         // Dp Array        int[][] matrix            = new int[strb.length()][stra.length()];               // String to character array        char[] charCrr = stra.toCharArray();        char[] charRrr = strb.toCharArray();         // initialize matrix with 1        for (int c = 0; c < stra.length(); c++)        {            if (charRrr[0] == charCrr)            {                matrix[0] = 1;            }        }         // for r from 1 to string length        for (int r = 1; r < charRrr.length; r++)        {            char ch = charRrr[r];             // for c from 1 b string length            for (int c = 1; c < charCrr.length; c++)            {                if (ch == charCrr                    && matrix[r - 1] == 1)                {                    matrix[r] = 1;                }            }        }         // For every query        for (int q : query)        {            int matLoc = (q + (strb.length() - 1));            if (matLoc >= stra.length()) {                System.out.println(false);            }            else            {                // print true                if (matrix[strb.length() - 1][matLoc]                    == 1)                {                    System.out.println(true);                }                else                {                    // print false                    System.out.println(false);                }            }        }     }       // Driver Code    public static void main(String[] args)    {        String stra = "GeeksForGeeks";        String strb = "Geeks";        int[] query = { 0,5,8 };        substringCheck(stra, strb, query);    } } // class// Code contributed by Swapnil Gupta
using System; public class GFG {    private static void    substringCheck(string stra, string strb, int[] query)    {         // Dp Array        int[, ] matrix = new int[strb.Length, stra.Length];         // String to character array        char[] charCrr = stra.ToCharArray();        char[] charRrr = strb.ToCharArray();         // initialize matrix with 1        for (int c = 0; c < stra.Length; c++) {            if (charRrr[0] == charCrr) {                matrix[0, c] = 1;            }        }         // for r from 1 to string length        for (int r = 1; r < charRrr.Length; r++) {            char ch = charRrr[r];             // for c from 1 b string length            for (int c = 1; c < charCrr.Length; c++) {                if (ch == charCrr                    && matrix[r - 1, c - 1] == 1) {                    matrix[r, c] = 1;                }            }        }         // For every query        foreach(int q in query)        {            int matLoc = (q + (strb.Length - 1));            if (matLoc >= stra.Length) {                Console.WriteLine(false);            }            else {                // print true                if (matrix[strb.Length - 1, matLoc] == 1) {                    Console.WriteLine(true);                }                else {                    // print false                    Console.WriteLine(false);                }            }        }    }     // Driver Code    public static void Main(string[] args)    {        string stra = "GeeksForGeeks";        string strb = "Geeks";        int[] query = { 0, 5, 8 };        substringCheck(stra, strb, query);    }} // This code is contributed by ukasp.
<script> function substringCheck(stra, strb, query){    // Dp Array    var matrix = Array.from(Array(strb.length), ()=>Array(stra.length));       // String to character array    var charCrr = stra.split('');    var charRrr = strb.split('');    // initialize matrix with 1    for (var c = 0; c < stra.length; c++)    {        if (charRrr[0] == charCrr)        {            matrix[0] = 1;        }    }    // for r from 1 to string length    for (var r = 1; r < charRrr.length; r++)    {        var ch = charRrr[r];        // for c from 1 b string length        for (var c = 1; c < charCrr.length; c++)        {            if (ch == charCrr                && matrix[r - 1] == 1)            {                matrix[r] = 1;            }        }    }    // For every query    for (var q of query)    {        var matLoc = (q + (strb.length - 1));        if (matLoc >= stra.length) {            document.write(false + "<br>");        }        else        {            // print true            if (matrix[strb.length - 1][matLoc]                == 1)            {                document.write(true+ "<br>");            }            else            {                // print false                document.write(false+ "<br>");            }        }    }} // Driver Codevar stra = "GeeksForGeeks";var strb = "Geeks";var query = [0,5,8];substringCheck(stra, strb, query); // This code is contributed by rutvik_56.</script>
true
false
true
Time Complexity: O(M*N)
princiraj1992
sanjeev2552
gswapnil246
kk773572498
ukasp
rrrtnx
rutvik_56
Hash
substring
Dynamic Programming
Strings
Hash
Strings
Dynamic Programming
Writing code in comment?
Please use ide.geeksforgeeks.org,
generate link and share the link here.
Comments
Old Comments
Bellman–Ford Algorithm | DP-23
Floyd Warshall Algorithm | DP-16
Longest Palindromic Substring | Set 1
Travelling Salesman Problem | Set 1 (Naive and Dynamic Programming)
Matrix Chain Multiplication | DP-8
Reverse a string in Java
Write a program to reverse an array or string
C++ Data Types
Write a program to print all permutations of a given string
Check for Balanced Brackets in an expression (well-formedness) using Stack