Find the Substing With One Whildcard Caracter Hackerrank Solution
Given a text and a wildcard pattern, implement wildcard pattern matching algorithm that finds if wildcard pattern is matched with text. The matching should cover the entire text (not partial text).
The wildcard pattern can include the characters '?' and '*'
'?' – matches any single character
'*' – Matches any sequence of characters (including the empty sequence)
For example,
Become a success story instead of just reading about them. Prepare for coding interviews at Amazon and other top product-based companies with our Amazon Test Series. Includes topic-wise practice questions on all important DSA topics along with 10 practice contests of 2 hours each. Designed by industry experts that will surely help you practice and sharpen your programming skills. Wait no more, start your preparation today!
Text = "baaabab", Pattern = "*****ba*****ab", output : true Pattern = "baaa?ab", output : true Pattern = "ba*a?", output : true Pattern = "a*ab", output : false
Each occurrence of '?' character in wildcard pattern can be replaced with any other character and each occurrence of '*' with a sequence of characters such that the wildcard pattern becomes identical to the input string after replacement.
Let's consider any character in the pattern.
Case 1: The character is '*'
Here two cases arise
- We can ignore '*' character and move to next character in the Pattern.
- '*' character matches with one or more characters in Text. Here we will move to next character in the string.
Case 2: The character is '?'
We can ignore current character in Text and move to next character in the Pattern and Text.
Case 3: The character is not a wildcard character
If current character in Text matches with current character in Pattern, we move to next character in the Pattern and Text. If they do not match, wildcard pattern and Text do not match.
We can use Dynamic Programming to solve this problem –
Let T[i][j] is true if first i characters in given string matches the first j characters of pattern.
DP Initialization:
// both text and pattern are null T[0][0] = true; // pattern is null T[i][0] = false; // text is null T[0][j] = T[0][j - 1] if pattern[j – 1] is '*'
DP relation :
// If current characters match, result is same as // result for lengths minus one. Characters match // in two cases: // a) If pattern character is '?' then it matches // with any character of text. // b) If current characters in both match if ( pattern[j – 1] == '?') || (pattern[j – 1] == text[i - 1]) T[i][j] = T[i-1][j-1] // If we encounter '*', two choices are possible- // a) We ignore '*' character and move to next // character in the pattern, i.e., '*' // indicates an empty sequence. // b) '*' character matches with ith character in // input else if (pattern[j – 1] == '*') T[i][j] = T[i][j-1] || T[i-1][j] else // if (pattern[j – 1] != text[i - 1]) T[i][j] = false
Below is the implementation of the above Dynamic Programming approach.
C++
#include <bits/stdc++.h>
using
namespace
std;
bool
strmatch(
char
str[],
char
pattern[],
int
n,
int
m)
{
if
(m == 0)
return
(n == 0);
bool
lookup[n + 1][m + 1];
memset
(lookup,
false
,
sizeof
(lookup));
lookup[0][0] =
true
;
for
(
int
j = 1; j <= m; j++)
if
(pattern[j - 1] ==
'*'
)
lookup[0][j] = lookup[0][j - 1];
for
(
int
i = 1; i <= n; i++) {
for
(
int
j = 1; j <= m; j++) {
if
(pattern[j - 1] ==
'*'
)
lookup[i][j]
= lookup[i][j - 1] || lookup[i - 1][j];
else
if
(pattern[j - 1] ==
'?'
|| str[i - 1] == pattern[j - 1])
lookup[i][j] = lookup[i - 1][j - 1];
else
lookup[i][j] =
false
;
}
}
return
lookup[n][m];
}
int
main()
{
char
str[] =
"baaabab"
;
char
pattern[] =
"*****ba*****ab"
;
if
(strmatch(str, pattern,
strlen
(str),
strlen
(pattern)))
cout <<
"Yes"
<< endl;
else
cout <<
"No"
<< endl;
return
0;
}
Java
import
java.util.Arrays;
public
class
GFG {
static
boolean
strmatch(String str, String pattern,
int
n,
int
m)
{
if
(m ==
0
)
return
(n ==
0
);
boolean
[][] lookup =
new
boolean
[n +
1
][m +
1
];
for
(
int
i =
0
; i < n +
1
; i++)
Arrays.fill(lookup[i],
false
);
lookup[
0
][
0
] =
true
;
for
(
int
j =
1
; j <= m; j++)
if
(pattern.charAt(j -
1
) ==
'*'
)
lookup[
0
][j] = lookup[
0
][j -
1
];
for
(
int
i =
1
; i <= n; i++)
{
for
(
int
j =
1
; j <= m; j++)
{
if
(pattern.charAt(j -
1
) ==
'*'
)
lookup[i][j] = lookup[i][j -
1
]
|| lookup[i -
1
][j];
else
if
(pattern.charAt(j -
1
) ==
'?'
|| str.charAt(i -
1
)
== pattern.charAt(j -
1
))
lookup[i][j] = lookup[i -
1
][j -
1
];
else
lookup[i][j] =
false
;
}
}
return
lookup[n][m];
}
public
static
void
main(String args[])
{
String str =
"baaabab"
;
String pattern =
"*****ba*****ab"
;
if
(strmatch(str, pattern, str.length(),
pattern.length()))
System.out.println(
"Yes"
);
else
System.out.println(
"No"
);
}
}
Python3
def
strrmatch(strr, pattern, n, m):
if
(m
=
=
0
):
return
(n
=
=
0
)
lookup
=
[[
False
for
i
in
range
(m
+
1
)]
for
j
in
range
(n
+
1
)]
lookup[
0
][
0
]
=
True
for
j
in
range
(
1
, m
+
1
):
if
(pattern[j
-
1
]
=
=
'*'
):
lookup[
0
][j]
=
lookup[
0
][j
-
1
]
for
i
in
range
(
1
, n
+
1
):
for
j
in
range
(
1
, m
+
1
):
if
(pattern[j
-
1
]
=
=
'*'
):
lookup[i][j]
=
lookup[i][j
-
1
]
or
lookup[i
-
1
][j]
elif
(pattern[j
-
1
]
=
=
'?'
or
strr[i
-
1
]
=
=
pattern[j
-
1
]):
lookup[i][j]
=
lookup[i
-
1
][j
-
1
]
else
:
lookup[i][j]
=
False
return
lookup[n][m]
strr
=
"baaabab"
pattern
=
"*****ba*****ab"
if
(strrmatch(strr, pattern,
len
(strr),
len
(pattern))):
print
(
"Yes"
)
else
:
print
(
"No"
)
C#
using
System;
class
GFG {
static
Boolean strmatch(String str,
String pattern,
int
n,
int
m)
{
if
(m == 0)
return
(n == 0);
Boolean[, ] lookup =
new
Boolean[n + 1, m + 1];
for
(
int
i = 0; i < n + 1; i++)
for
(
int
j = 0; j < m + 1; j++)
lookup[i, j] =
false
;
lookup[0, 0] =
true
;
for
(
int
j = 1; j <= m; j++)
if
(pattern[j - 1] ==
'*'
)
lookup[0, j] = lookup[0, j - 1];
for
(
int
i = 1; i <= n; i++) {
for
(
int
j = 1; j <= m; j++) {
if
(pattern[j - 1] ==
'*'
)
lookup[i, j] = lookup[i, j - 1]
|| lookup[i - 1, j];
else
if
(pattern[j - 1] ==
'?'
|| str[i - 1] == pattern[j - 1])
lookup[i, j] = lookup[i - 1, j - 1];
else
lookup[i, j] =
false
;
}
}
return
lookup[n, m];
}
public
static
void
Main(String[] args)
{
String str =
"baaabab"
;
String pattern =
"*****ba*****ab"
;
if
(strmatch(str, pattern, str.Length,
pattern.Length))
Console.WriteLine(
"Yes"
);
else
Console.WriteLine(
"No"
);
}
}
Time complexity: O(m x n)
Auxiliary space: O(m x n)
DP Memoization solution:-
C++
#include <bits/stdc++.h>
using
namespace
std;
vector<vector<
int
> > dp;
int
finding(string& s, string& p,
int
n,
int
m)
{
if
(n < 0 && m < 0)
return
1;
if
(m < 0)
return
0;
if
(n < 0)
{
while
(m >= 0)
{
if
(p[m] !=
'*'
)
return
0;
m--;
}
return
1;
}
if
(dp[n][m] == -1)
{
if
(p[m] ==
'*'
)
{
return
dp[n][m] = finding(s, p, n - 1, m)
|| finding(s, p, n, m - 1);
}
else
{
if
(p[m] != s[n] && p[m] !=
'?'
)
return
dp[n][m] = 0;
else
return
dp[n][m]
= finding(s, p, n - 1, m - 1);
}
}
return
dp[n][m];
}
bool
isMatch(string s, string p)
{
dp.clear();
dp.resize(s.size() + 1, vector<
int
>(p.size() + 1, -1));
return
dp[s.size()][p.size()]
= finding(s, p, s.size() - 1, p.size() - 1);
}
int
main()
{
string str =
"baaabab"
;
string pattern =
"*****ba*****ab"
;
if
(isMatch(str, pattern))
cout <<
"Yes"
<< endl;
else
cout <<
"No"
<< endl;
return
0;
}
Time complexity: O(m x n).
Auxiliary space:O(m x n).
Further Improvements:
We can improve space complexity by making use of the fact that we only uses the result from last row.
One more improvement is you can merge consecutive '*' in the pattern to single '*' as they mean the same thing. For example for pattern "*****ba*****ab", if we merge consecutive stars, the resultant string will be "*ba*ab". So, value of m is reduced from 14 to 6.
This article is contributed by Aditya Goel. If you like GeeksforGeeks and would like to contribute, you can also write an article and mail your article to review-team@geeksforgeeks.org. See your article appearing on the GeeksforGeeks main page and help other Geeks.
Please write comments if you find anything incorrect, or you want to share more information about the topic discussed above
Find the Substing With One Whildcard Caracter Hackerrank Solution
Source: https://www.geeksforgeeks.org/wildcard-pattern-matching/