When we talk about substring search, we're generally referring to the task of finding a specific pattern within a larger string. This becomes more interesting when we introduce wildcards, which are special characters that can represent one or more characters in a string. The most common wildcard characters are ?
, which matches any single character, and *
, which matches any sequence of characters (including an empty sequence).
?
Wildcard:
h?llo
hello
, hallo
, h3llo
hlllo
*
Wildcard:
h*llo
hello
, helloo
, hworldllo
, hlllo
*
can be empty)Combination:
h*llo?
helloX
, helloo5
, hworldlloZ
hlllo
, hello
Wildcards allow for more flexible searching compared to fixed patterns, which is particularly useful in situations where the exact content may vary but the structure remains constant. A common real-world example is searching through a database of usernames or files where you may not remember the exact name but only parts of it.
The simplest way to handle substring searching with wildcards is the naive approach. This is straightforward but inefficient for larger strings. Here’s how it works:
*
, skip through all matching characters.?
or matches the character in the string, proceed.Complexity: O(n * m) in the worst case, where n
is the length of the main string and m
is the length of the pattern.
def wildcard_match(s, p): def match(i, j): if j == len(p): return i == len(s) if i < len(s) and (p[j] == s[i] or p[j] == '?'): return match(i + 1, j + 1) if p[j] == '*': return match(i, j + 1) or (i < len(s) and match(i + 1, j)) return False return match(0, 0)
A more efficient method to handle wildcard substring search is by utilizing dynamic programming. The idea is to build a 2D table where the cell dp[i][j]
signifies whether the first i
characters in the string s
match the first j
characters in the pattern p
.
(n+1) x (m+1)
initialized to False
.dp[0][0]
to True
(empty pattern matches empty string).*
that can match an empty string.?
, carry forward as well.*
, consider both scenarios: matching one-less character or using the *
to match multiple characters.Complexity: O(n * m)
def wildcard_match_dp(s, p): n, m = len(s), len(p) dp = [[False] * (m + 1) for _ in range(n + 1)] dp[0][0] = True for j in range(1, m + 1): if p[j - 1] == '*': dp[0][j] = dp[0][j - 1] for i in range(1, n + 1): for j in range(1, m + 1): if p[j - 1] == '*': dp[i][j] = dp[i][j - 1] or dp[i - 1][j] elif p[j - 1] == s[i - 1] or p[j - 1] == '?': dp[i][j] = dp[i - 1][j - 1] return dp[n][m]
Understanding and implementing substring search algorithms that support wildcards plays a crucial role in various fields, including:
Staying equipped with these substring search methods will not only prepare you for coding interviews but also enhance your problem-solving toolkit for real-world applications.
16/11/2024 | DSA
15/11/2024 | DSA
23/09/2024 | DSA
15/11/2024 | DSA
13/10/2024 | DSA
08/12/2024 | DSA
23/09/2024 | DSA
23/09/2024 | DSA
23/09/2024 | DSA
23/09/2024 | DSA
23/09/2024 | DSA