LeetCode 0010. Regular Expression Matching Solution in Java, C++, Python & More | Explanation + Code

CoderIndeed
0
0010. Regular Expression Matching

Description

Given an input string s and a pattern p, implement regular expression matching with support for '.' and '*' where:

  • '.' Matches any single character.​​​​
  • '*' Matches zero or more of the preceding element.

Return a boolean indicating whether the matching covers the entire input string (not partial).

 

Example 1:

Input: s = "aa", p = "a"
Output: false
Explanation: "a" does not match the entire string "aa".

Example 2:

Input: s = "aa", p = "a*"
Output: true
Explanation: '*' means zero or more of the preceding element, 'a'. Therefore, by repeating 'a' once, it becomes "aa".

Example 3:

Input: s = "ab", p = ".*"
Output: true
Explanation: ".*" means "zero or more (*) of any character (.)".

 

Constraints:

  • 1 <= s.length <= 20
  • 1 <= p.length <= 20
  • s contains only lowercase English letters.
  • p contains only lowercase English letters, '.', and '*'.
  • It is guaranteed for each appearance of the character '*', there will be a previous valid character to match.

Solutions

Solution 1: Memoization Search

We design a function dfs(i, j), which indicates whether the i-th character of s matches the j-th character of p. The answer is dfs(0, 0).

The calculation process of the function dfs(i, j) is as follows:

  • If j has reached the end of p, then if i has also reached the end of s, the match is successful, otherwise, the match fails.
  • If the next character of j is '*', we can choose to match 0 s[i] characters, which is dfs(i, j + 2). If i \lt m and s[i] matches p[j], we can choose to match 1 s[i] character, which is dfs(i + 1, j).
  • If the next character of j is not '*', then if i \lt m and s[i] matches p[j], it is dfs(i + 1, j + 1). Otherwise, the match fails.

During the process, we can use memoization search to avoid repeated calculations.

The time complexity is O(m × n), and the space complexity is O(m × n). Here, m and n are the lengths of s and p respectively.

PythonJavaC++GoRustJavaScriptC#CPHP
class Solution: def isMatch(self, s: str, p: str) -> bool: @cache def dfs(i, j): if j >= n: return i == m if j + 1 < n and p[j + 1] == '*': return dfs(i, j + 2) or ( i < m and (s[i] == p[j] or p[j] == '.') and dfs(i + 1, j) ) return i < m and (s[i] == p[j] or p[j] == '.') and dfs(i + 1, j + 1) m, n = len(s), len(p) return dfs(0, 0)(code-box)

Solution 2: Dynamic Programming

We can convert the memoization search in Solution 1 into dynamic programming.

Define f[i][j] to represent whether the first i characters of string s match the first j characters of string p. The answer is f[m][n]. Initialize f[0][0] = true, indicating that the empty string and the empty regular expression match.

Similar to Solution 1, we can discuss different cases.

  • If p[j - 1] is '*', we can choose to match 0 s[i - 1] characters, which is f[i][j] = f[i][j - 2]. If s[i - 1] matches p[j - 2], we can choose to match 1 s[i - 1] character, which is f[i][j] = f[i][j] \lor f[i - 1][j].
  • If p[j - 1] is not '*', then if s[i - 1] matches p[j - 1], it is f[i][j] = f[i - 1][j - 1]. Otherwise, the match fails.

The time complexity is O(m × n), and the space complexity is O(m × n). Here, m and n are the lengths of s and p respectively.

PythonJavaC++GoRustJavaScriptC#PHPC
class Solution: def isMatch(self, s: str, p: str) -> bool: m, n = len(s), len(p) f = [[False] * (n + 1) for _ in range(m + 1)] f[0][0] = True for i in range(m + 1): for j in range(1, n + 1): if p[j - 1] == "*": f[i][j] = f[i][j - 2] if i > 0 and (p[j - 2] == "." or s[i - 1] == p[j - 2]): f[i][j] |= f[i - 1][j] elif i > 0 and (p[j - 1] == "." or s[i - 1] == p[j - 1]): f[i][j] = f[i - 1][j - 1] return f[m][n](code-box)

Post a Comment

0Comments

Post a Comment (0)

#buttons=(Accept !) #days=(20)

Our website uses cookies to enhance your experience. Check Now
Accept !