From 0cd88af4ff41118bc20b9971affb00b60b92dd5a Mon Sep 17 00:00:00 2001 From: AmirMohammad Hosseini Nasab Date: Fri, 12 Aug 2022 12:52:38 +0430 Subject: [PATCH] Add dp solution to regex_match.py --- dynamic_programming/regex_match.py | 47 ++++++++++++++++++++++++++++++ 1 file changed, 47 insertions(+) diff --git a/dynamic_programming/regex_match.py b/dynamic_programming/regex_match.py index b390d6eae..dc76eedeb 100644 --- a/dynamic_programming/regex_match.py +++ b/dynamic_programming/regex_match.py @@ -25,6 +25,8 @@ def recursive_match(text: str, pattern: str) -> bool: True >>> recursive_match('abc', 'a.c*d') False + >>> recursive_match('aa', '.*') + True """ if not text and not pattern: return True @@ -47,6 +49,51 @@ def recursive_match(text: str, pattern: str) -> bool: return False +def dp_match(text: str, pattern: str) -> bool: + """ + Dynamic programming matching algorithm. + + Time complexity: O(m * n), where m is the length of text and n is the length of pattern. + Space complexity: O(m * n). + + :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 i in range(1, m + 1): + dp[i][0] = False + + 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] == '.' or pattern[j - 1] == text[i - 1]: + dp[i][j] = dp[i - 1][j - 1] + elif pattern[j - 1] == '*': + dp[i][j] = dp[i][j - 2] or (dp[i - 1][j] and (pattern[j - 2] == '.' or pattern[j - 2] == text[i - 1])) + else: + dp[i][j] = False + + return dp[m][n] + + if __name__ == "__main__": import doctest