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

• Difficulty Level : Expert
• Last Updated : 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++

 `// C++ implementation of the approach``#include ``#define mod 3803``#define d 26``using` `namespace` `std;` `int` `hash_b;``int``* hash_a;``int``* mul;` `// Function to return the modular inverse``// using Fermat's little theorem``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``void` `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 b``bool` `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``int` `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

 `// Java implementation of the approach``import` `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

 `# Python3 implementation of the approach``mod ``=` `3803``d ``=` `26` `hash_b ``=` `0``hash_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 Code``if` `__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#

 `// C# implementation of the approach``using` `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 */`

Javascript

 ``
Output
```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

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

C#

 `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.`

Javascript

 ``
Output
```true
false
true```

Time Complexity: O(M*N)

My Personal Notes arrow_drop_up