Queries to check if string B exists as substring in string A
Last Updated :
17 Apr, 2023
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++
#include <bits/stdc++.h>
#define mod 3803
#define d 26
using namespace std;
int hash_b;
int * hash_a;
int * mul;
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;
}
void genHash(string& a, string& b)
{
hash_a = new int [a.size()];
mul = new int [a.size()];
for ( int i = b.size() - 1; i >= 0; i--)
hash_b = (hash_b * d + (b[i] - 97)) % mod;
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;
}
}
bool checkEqual( int i, int len_a, int len_b)
{
int x;
if (i == 0)
x = hash_a[len_b - 1];
else {
x = (hash_a[i + len_b - 1] - hash_a[i - 1]
+ 2 * mod)
% mod;
x = (x * mi(mul[i])) % mod;
}
if (x == hash_b)
return true ;
return false ;
}
int main()
{
string a = "abababababa" ;
string b = "aba" ;
genHash(a, b);
int queries[] = { 0, 1, 2, 3 };
int q = sizeof (queries) / sizeof (queries[0]);
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
import java.util.*;
class GFG {
static int mod = 3803 ;
static int d = 26 ;
static int hash_b;
static int [] hash_a;
static int [] mul;
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;
}
static void genHash( char [] a, char [] b)
{
hash_a = new int [a.length];
mul = new int [a.length];
for ( int i = b.length - 1 ; i >= 0 ; i--) {
hash_b = (hash_b * d + (b[i] - 97 )) % mod;
}
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;
}
}
static boolean checkEqual( int i, int len_a, int len_b)
{
int x;
if (i == 0 ) {
x = hash_a[len_b - 1 ];
}
else {
x = (hash_a[i + len_b - 1 ] - hash_a[i - 1 ]
+ 2 * mod)
% mod;
x = (x * mi(mul[i])) % mod;
}
if (x == hash_b) {
return true ;
}
return false ;
}
public static void main(String[] args)
{
String a = "abababababa" ;
String b = "aba" ;
genHash(a.toCharArray(), b.toCharArray());
int queries[] = { 0 , 1 , 2 , 3 };
int q = queries.length;
for ( int i = 0 ; i < q; i++) {
if (checkEqual(queries[i], a.length(),
b.length())) {
System.out.println( "Yes" );
}
else {
System.out.println( "No" );
}
}
}
}
|
Python3
mod = 3803
d = 26
hash_b = 0
hash_a = []
mul = []
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
def genHash(a, b):
global hash_b, hash_a, mul, d, mod
hash_a = [ 0 ] * len (a)
mul = [ 0 ] * len (a)
for i in range ( len (b) - 1 , - 1 , - 1 ):
hash_b = (hash_b * d +
( ord (b[i]) - 97 )) % mod
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
def checkEqual(i, len_a, len_b):
global hash_b, hash_a, mul, d, mod
x = - 1
if i = = 0 :
x = hash_a[len_b - 1 ]
else :
x = (hash_a[i + len_b - 1 ] -
hash_a[i - 1 ] + 2 * mod) % mod
x = (x * mi(mul[i])) % mod
if x = = hash_b:
return True
return False
if __name__ = = "__main__" :
a = "abababababa"
b = "aba"
genHash(a, b)
queries = [ 0 , 1 , 2 , 3 ]
q = len (queries)
for i in range (q):
if checkEqual(queries[i], len (a), len (b)):
print ( "Yes" )
else :
print ( "No" )
|
C#
using System;
class GFG {
static int mod = 3803;
static int d = 26;
static int hash_b;
static int [] hash_a;
static int [] mul;
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;
}
static void genHash( char [] a, char [] b)
{
hash_a = new int [a.Length];
mul = new int [a.Length];
for ( int i = b.Length - 1; i >= 0; i--) {
hash_b = (hash_b * d + (b[i] - 97)) % mod;
}
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;
}
}
static Boolean checkEqual( int i, int len_a, int len_b)
{
int x;
if (i == 0) {
x = hash_a[len_b - 1];
}
else {
x = (hash_a[i + len_b - 1] - hash_a[i - 1]
+ 2 * mod)
% mod;
x = (x * mi(mul[i])) % mod;
}
if (x == hash_b) {
return true ;
}
return false ;
}
public static void Main(String[] args)
{
String a = "abababababa" ;
String b = "aba" ;
genHash(a.ToCharArray(), b.ToCharArray());
int [] queries = { 0, 1, 2, 3 };
int q = queries.Length;
for ( int i = 0; i < q; i++) {
if (checkEqual(queries[i], a.Length,
b.Length)) {
Console.WriteLine( "Yes" );
}
else {
Console.WriteLine( "No" );
}
}
}
}
|
Javascript
<script>
var mod = 3803;
var d = 26;
var hash_b = 0;
var hash_a = [];
var mul = [];
function 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 genHash(a, b)
{
hash_a = Array(a.length).fill(0);
mul = Array(a.length).fill(0);
for ( var i = b.length - 1; i >= 0; i--)
hash_b = (hash_b * d + (b[i].charCodeAt(0) - 97)) % mod;
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 checkEqual(i, len_a, len_b)
{
var x;
if (i == 0)
x = hash_a[len_b - 1];
else {
x = (hash_a[i + len_b - 1] - hash_a[i - 1]
+ 2 * mod)
% mod;
x = (x * mi(mul[i])) % mod;
}
if (x == hash_b)
return true ;
return false ;
}
var a = "abababababa" ;
var b = "aba" ;
genHash(a.split(' '), b.split(' '));
var queries = [0, 1, 2, 3];
var q = queries.length
for ( var i = 0; i < q; i++) {
if (checkEqual(queries[i], a.length, b.length))
document.write( "Yes<br>" );
else
document.write( "No<br>" );
}
</script>
|
Time Complexity: O(N*Q)
Auxiliary Space: O(M*N)
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.
C++
#include <bits/stdc++.h>
using namespace std;
void substringCheck(string stra, string strb,
vector< int > query)
{
int matrix[strb.size()][stra.size()];
for ( int c = 0; c < stra.size(); c++) {
if (strb[0] == stra) {
matrix[0] = 1;
}
}
for ( int r = 1; r < strb.size(); r++) {
char ch = strb[r];
for ( int c = 1; c < stra.size(); c++) {
if (ch == stra
&& matrix[r - 1] == 1) {
matrix[r] = 1;
}
}
}
for ( auto q : query) {
int matLoc = (q + (strb.size() - 1));
if (matLoc >= stra.size()) {
cout << "false" << endl;
}
else {
if (matrix[strb.size() - 1][(matLoc)] == 1) {
cout << "true" << endl;
}
else {
cout << "false" << endl;
}
}
}
}
int main()
{
string stra = "GeeksForGeeks" ;
string strb = "Geeks" ;
vector< int > query = { 0, 5, 8 };
substringCheck(stra, strb, query);
}
|
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)
{
int [][] matrix
= new int [strb.length()][stra.length()];
char [] charCrr = stra.toCharArray();
char [] charRrr = strb.toCharArray();
for ( int c = 0 ; c < stra.length(); c++)
{
if (charRrr[ 0 ] == charCrr)
{
matrix[ 0 ] = 1 ;
}
}
for ( int r = 1 ; r < charRrr.length; r++)
{
char ch = charRrr[r];
for ( int c = 1 ; c < charCrr.length; c++)
{
if (ch == charCrr
&& matrix[r - 1 ] == 1 )
{
matrix[r] = 1 ;
}
}
}
for ( int q : query)
{
int matLoc = (q + (strb.length() - 1 ));
if (matLoc >= stra.length()) {
System.out.println( false );
}
else
{
if (matrix[strb.length() - 1 ][(matLoc)]
== 1 )
{
System.out.println( true );
}
else
{
System.out.println( false );
}
}
}
}
public static void main(String[] args)
{
String stra = "GeeksForGeeks" ;
String strb = "Geeks" ;
int [] query = { 0 , 5 , 8 };
substringCheck(stra, strb, query);
}
}
|
Python3
def substringCheck(stra, strb, query):
n = len (stra)
m = len (strb)
matrix = [[ - 1 ] * n for _ in range (m)]
for c in range (n):
if strb[ 0 ] = = stra:
matrix[ 0 ] = 1
for r in range ( 1 , m):
ch = strb[r]
for c in range ( 1 , n):
if ch = = stra and matrix[r - 1 ] = = 1 :
matrix[r] = 1
for q in query:
matLoc = q + (m - 1 )
if matLoc > = n:
print ( "false" )
else :
if matrix[m - 1 ][(matLoc)] = = 1 :
print ( "true" )
else :
print ( "false" )
if __name__ = = "__main__" :
stra = "GeeksForGeeks"
strb = "Geeks"
query = [ 0 , 5 , 8 ]
substringCheck(stra, strb, query)
|
C#
using System;
public class GFG {
private static void
substringCheck( string stra, string strb, int [] query)
{
int [, ] matrix = new int [strb.Length, stra.Length];
char [] charCrr = stra.ToCharArray();
char [] charRrr = strb.ToCharArray();
for ( int c = 0; c < stra.Length; c++) {
if (charRrr[0] == charCrr) {
matrix[0, c] = 1;
}
}
for ( int r = 1; r < charRrr.Length; r++) {
char ch = charRrr[r];
for ( int c = 1; c < charCrr.Length; c++) {
if (ch == charCrr
&& matrix[r - 1, c - 1] == 1) {
matrix[r, c] = 1;
}
}
}
foreach ( int q in query)
{
int matLoc = (q + (strb.Length - 1));
if (matLoc >= stra.Length) {
Console.WriteLine( false );
}
else {
if (matrix[strb.Length - 1, matLoc] == 1) {
Console.WriteLine( true );
}
else {
Console.WriteLine( false );
}
}
}
}
public static void Main( string [] args)
{
string stra = "GeeksForGeeks" ;
string strb = "Geeks" ;
int [] query = { 0, 5, 8 };
substringCheck(stra, strb, query);
}
}
|
Javascript
<script>
function substringCheck(stra, strb, query)
{
var matrix = Array.from(Array(strb.length), ()=>Array(stra.length));
var charCrr = stra.split( '' );
var charRrr = strb.split( '' );
for ( var c = 0; c < stra.length; c++)
{
if (charRrr[0] == charCrr)
{
matrix[0] = 1;
}
}
for ( var r = 1; r < charRrr.length; r++)
{
var ch = charRrr[r];
for ( var c = 1; c < charCrr.length; c++)
{
if (ch == charCrr
&& matrix[r - 1] == 1)
{
matrix[r] = 1;
}
}
}
for ( var q of query)
{
var matLoc = (q + (strb.length - 1));
if (matLoc >= stra.length) {
document.write( false + "<br>" );
}
else
{
if (matrix[strb.length - 1][(matLoc)]
== 1)
{
document.write( true + "<br>" );
}
else
{
document.write( false + "<br>" );
}
}
}
}
var stra = "GeeksForGeeks" ;
var strb = "Geeks" ;
var query = [0,5,8];
substringCheck(stra, strb, query);
</script>
|
Time Complexity: O(M*N)
Auxiliary Space: O(M*N)
Like Article
Suggest improvement
Share your thoughts in the comments
Please Login to comment...