mirror of
https://github.com/TheAlgorithms/Python.git
synced 2024-11-23 21:11:08 +00:00
Add: Two Regex match algorithm (Recursive & DP) (#6321)
* Add recursive solution to regex_match.py * Add dp solution to regex_match.py * Add link to regex_match.py * Minor edit * Minor change * Minor change * Update dynamic_programming/regex_match.py Co-authored-by: Tianyi Zheng <tianyizheng02@gmail.com> * Update dynamic_programming/regex_match.py Co-authored-by: Tianyi Zheng <tianyizheng02@gmail.com> * Fix ruff formatting in if statements * Update dynamic_programming/regex_match.py Co-authored-by: Tianyi Zheng <tianyizheng02@gmail.com> * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci --------- Co-authored-by: Tianyi Zheng <tianyizheng02@gmail.com> Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com>
This commit is contained in:
parent
9d86d4edaa
commit
f24ab2c60d
97
dynamic_programming/regex_match.py
Normal file
97
dynamic_programming/regex_match.py
Normal file
|
@ -0,0 +1,97 @@
|
|||
"""
|
||||
Regex matching check if a text matches pattern or not.
|
||||
Pattern:
|
||||
'.' Matches any single character.
|
||||
'*' Matches zero or more of the preceding element.
|
||||
More info:
|
||||
https://medium.com/trick-the-interviwer/regular-expression-matching-9972eb74c03
|
||||
"""
|
||||
|
||||
|
||||
def recursive_match(text: str, pattern: str) -> bool:
|
||||
"""
|
||||
Recursive matching algorithm.
|
||||
|
||||
Time complexity: O(2 ^ (|text| + |pattern|))
|
||||
Space complexity: Recursion depth is O(|text| + |pattern|).
|
||||
|
||||
:param text: Text to match.
|
||||
:param pattern: Pattern to match.
|
||||
:return: True if text matches pattern, False otherwise.
|
||||
|
||||
>>> recursive_match('abc', 'a.c')
|
||||
True
|
||||
>>> recursive_match('abc', 'af*.c')
|
||||
True
|
||||
>>> recursive_match('abc', 'a.c*')
|
||||
True
|
||||
>>> recursive_match('abc', 'a.c*d')
|
||||
False
|
||||
>>> recursive_match('aa', '.*')
|
||||
True
|
||||
"""
|
||||
if not pattern:
|
||||
return not text
|
||||
|
||||
if not text:
|
||||
return pattern[-1] == "*" and recursive_match(text, pattern[:-2])
|
||||
|
||||
if text[-1] == pattern[-1] or pattern[-1] == ".":
|
||||
return recursive_match(text[:-1], pattern[:-1])
|
||||
|
||||
if pattern[-1] == "*":
|
||||
return recursive_match(text[:-1], pattern) or recursive_match(
|
||||
text, pattern[:-2]
|
||||
)
|
||||
|
||||
return False
|
||||
|
||||
|
||||
def dp_match(text: str, pattern: str) -> bool:
|
||||
"""
|
||||
Dynamic programming matching algorithm.
|
||||
|
||||
Time complexity: O(|text| * |pattern|)
|
||||
Space complexity: O(|text| * |pattern|)
|
||||
|
||||
:param text: Text to match.
|
||||
:param pattern: Pattern to match.
|
||||
:return: True if text matches pattern, False otherwise.
|
||||
|
||||
>>> dp_match('abc', 'a.c')
|
||||
True
|
||||
>>> dp_match('abc', 'af*.c')
|
||||
True
|
||||
>>> dp_match('abc', 'a.c*')
|
||||
True
|
||||
>>> dp_match('abc', 'a.c*d')
|
||||
False
|
||||
>>> dp_match('aa', '.*')
|
||||
True
|
||||
"""
|
||||
m = len(text)
|
||||
n = len(pattern)
|
||||
dp = [[False for _ in range(n + 1)] for _ in range(m + 1)]
|
||||
dp[0][0] = True
|
||||
|
||||
for j in range(1, n + 1):
|
||||
dp[0][j] = pattern[j - 1] == "*" and dp[0][j - 2]
|
||||
|
||||
for i in range(1, m + 1):
|
||||
for j in range(1, n + 1):
|
||||
if pattern[j - 1] in {".", text[i - 1]}:
|
||||
dp[i][j] = dp[i - 1][j - 1]
|
||||
elif pattern[j - 1] == "*":
|
||||
dp[i][j] = dp[i][j - 2]
|
||||
if pattern[j - 2] in {".", text[i - 1]}:
|
||||
dp[i][j] |= dp[i - 1][j]
|
||||
else:
|
||||
dp[i][j] = False
|
||||
|
||||
return dp[m][n]
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
import doctest
|
||||
|
||||
doctest.testmod()
|
Loading…
Reference in New Issue
Block a user