In this article, we will see Pattern matching with wildcards which is an encountered problem, in the field of computer science and string manipulation. The objective is to determine whether a given wildcard pattern matches a string or not. In this article, we will discuss the step-by-step algorithm for wildcard pattern matching providing code examples in JavaScript.
Understanding Wildcard Patterns
A wildcard pattern consists of letters as special symbols like
- ‘*’ which represents a sequence of characters (including an empty space)
- ‘?’ which represents a single character.
Example:
Text = "neveropen", Pattern = “*****Ge*****ks", output: true Pattern = "Geeksfor?eeks", output: true Pattern = "Ge*k?", output: true Pattern = "e*ks", output: false
Approaches for Wildcard Pattern Matching
- Javascript Regular Expression
- Pattern-Matching Algorithm
Wildcard Pattern Matching using Javascript Regular Expression
JavaScript offers support, for expressions, which provides a convenient way to handle wildcard pattern matching. Regular expressions are patterns that are used to find character combinations within strings.
Here is an example of how you can utilize expressions in JavaScript to perform pattern matching:
Syntax:
function wildcardMatch(text, pattern) { const regexPattern = new RegExp('^' + pattern.replace(/\?/g, '.').replace(/\*/g, '.*') + '$'); return regexPattern.test(text); }
Parameters:
- text: It is the main string that is to be checked.
- pattern: It is the wildcard pattern that is used to check the specific pattern in the text.
In this implementation:
- The wildcardMatchRegExp function converts the given wildcard pattern into a regular expression pattern. It replaces ‘?’ with ‘.’ to match any character. With ‘.’ to match zero or more characters.
- To ensure that the entire string matches the pattern the regular expression is anchored at the start (^). End ($) of the string.
- The test method of the regular expression object is used to check if the text matches the pattern.
This approach is concise. Leverages JavaScripts built-in functionality, for expressions enabling efficient handling of wildcard pattern matching. Similarly, you can add test cases by providing text and pattern values and verifying their results.
Example: This example demonstrates the above-mentioned approach.
Javascript
function wildcardMatchRegExp(text, pattern) { // Convert wildcard pattern to a // regular expression pattern const regexPattern = new RegExp( "^" + pattern .replace(/\?/g, "." ) .replace(/\*/g, ".*" ) + "$" ); // Test if the text matches the // regular expression pattern return regexPattern.test(text); } // Test case const text = "neveropen" ; const pattern = "*****Ge****ks" ; if (wildcardMatchRegExp(text, pattern)) { console.log( "Pattern is Matched" ); } else { console.log( "Pattern is not matched" ); } |
Pattern is Matched
Wildcard Pattern Matching using Pattern-Matching Algorithm
The algorithm deals with symbols, in the pattern like ‘*’ which matches sequences of characters ( empty ones), and ‘?’, which matches just one character.
Algorithm Steps:
Let’s break down the steps involved in the pattern-matching algorithm:
- Calculate the length of both the text (n) and the pattern (m).
- If any of the patterns is an empty string i.e. n==0 or m == 0. then return false.
- Use a JavaScript loop with two pointers i and j, to iterate both the string and apply matching.
- Increase both i and j by 1 when:
- character at text[i] and pattern[j] are same.
- pattern[j] is a symbol ‘?’.
- Store the values of i and j as textPointer and pattPointer if j encounters the ‘*’ symbol and increament j to move past the ‘*’ symbols
- If the pattpointer is updated increment i, j, textPointer by 1.
- Iterate while j is within bounds and pattern[j] is a ‘*’ symbol, increment j to move past the ‘*’.
- If the j pointer reaches the end of the pattern i.e. j == m return true else return false.
Example: Below is the implementation of the above algorithm in JavaScript.
Javascript
function wildcard(text, pattern) { const n = text.length; const m = pattern.length; if (m === 0) { return n === 0; } let i = 0, j = 0, textPointer = -1, pattPointer = -1; while (i < n) { if (text[i] === pattern[j]) { i++; j++; } else if (j < m && pattern[j] === "?" ) { i++; j++; } else if (j < m && pattern[j] === "*" ) { textPointer = i; pattPointer = j; j++; } else if (pattPointer !== -1) { j = pattPointer + 1; i = textPointer + 1; textPointer++; } else { return false ; } } while (j < m && pattern[j] === "*" ) { j++; } return j === m; } // Test case const text = "neveropen" ; const pattern = "*****Ge****ks" ; if (wildcard(text, pattern)) { console.log( "Pattern is Matched" ); } else { console.log( "Pattern is not Matched" ); } |
Pattern is Matched
Time Complexity: O(n*m) where “n” is the length of the text string, and “m” is the length of the pattern string.
Space Complexity: O(n+m) where “n” is the length of the text string, and “m” is the length of the pattern string.