LeetCodeDifficult-【面試題19. 正則表達式匹配】

請實現一個函數用來匹配包含’. ‘和’‘的正則表達式。模式中的字符’.‘表示任意一個字符,而’'表示它前面的字符可以出現任意次(含0次)。在本題中,匹配是指字符串的所有字符匹配整個模式。例如,字符串"aaa"與模式"a.a"和"abaca"匹配,但與"aa.a"和"ab*a"均不匹配。

示例 1:

輸入:
s = “aa”
p = “a”
輸出: false
解釋: “a” 無法匹配 “aa” 整個字符串。

示例 2:

輸入:
s = “aa”
p = “a*”
輸出: true
解釋: 因爲 ‘*’ 代表可以匹配零個或多個前面的那一個元素, 在這裏前面的元素就是 ‘a’。因此,字符串 “aa” 可被視爲 ‘a’ 重複了一次。

示例 3:

輸入:
s = “ab”
p = “."
輸出: true
解釋: ".
” 表示可匹配零個或多個(’*’)任意字符(’.’)。

示例 4:

輸入:
s = “aab”
p = “cab”
輸出: true
解釋: 因爲 ‘*’ 表示零個或多個,這裏 ‘c’ 爲 0 個, ‘a’ 被重複一次。因此可以匹配字符串 “aab”。

示例 5:

輸入:
s = “mississippi”
p = “misisp*.”
輸出: false
s 可能爲空,且只包含從 a-z 的小寫字母。
p 可能爲空,且只包含從 a-z 的小寫字母,以及字符 . 和 *。

注意:本題與主站 10 題相同:https://leetcode-cn.com/problems/regular-expression-matching/
來源:力扣(LeetCode)
鏈接:https://leetcode-cn.com/problems/zheng-ze-biao-da-shi-pi-pei-lcof
著作權歸領釦網絡所有。商業轉載請聯繫官方授權,非商業轉載請註明出處。

思路1:遞規

這題的類別是Difficult級別的,初看確實有的不好考慮,特別是剛開始準備純靠邏輯判斷來做,發現後面情況太多,單純判斷不好做。於是看了題解,一堆用dp和遞歸來做了。但是dp的看了需求還是有的地方沒太懂,於是自己用遞歸做出來了。想到用遞歸後思路其實很清晰,就是有的需要考慮的很全面才行。
具體的細節可以看代碼。
個人認爲dp其實就是遞推,它其實就是和遞歸相反,它是從正面推算,而遞歸這較爲簡單,它是從後往前算。
在這裏插入圖片描述

  • 第一份代碼我假設了一個字符串中不會出現的字符#,加在需要判單字符串的開頭,這樣就避免判空的過程。
  • 第二份代碼具備了一般性
class Solution:
    def isMatch(self, s: str, p: str) -> bool:
        def match(s, p) ->bool:
            if s == p:
                return True
            if s == '' or p == '':
                return False
            if s[-1] == p[-1] or (p[-1] == '.' and s[-1] != '#'):
                return match(s[:-1], p[:-1])
            if p[-1] == '*':
                if len(p)>=2:
                    if p[-2] == s[-1] or (p[-2] == '.' and s[-1] != '#'):
                        # *匹配0個、一個或者多個
                        return match(s, p[:-2]) or match(s[:-1], p[:-2]) or match(s[:-1], p)
                    else:
                        # 不能匹配
                        return match(s, p[:-2])
            return False
        # 遞歸解法
        return match('#'+s, '#'+p)
class Solution:
    def isMatch(self, s: str, p: str) -> bool:
        def match(s, p) ->bool:
            if s == p:
                return True
            if s != '' and p == '':
                return False
            elif s == '' and p != '':
                if p[-1] == '*':
                    if len(p)>=2:
                        return match(s, p[:-2])
                return False
            else:
                if s[-1] == p[-1] or p[-1] == '.':
                    return match(s[:-1], p[:-1])
                if p[-1] == '*':
                    if len(p)>=2:
                        if p[-2] == s[-1] or p[-2] == '.':
                            # *匹配0個、一個或者多個
                            return match(s, p[:-2]) or match(s[:-1], p[:-2]) or match(s[:-1], p)
                        else:
                            # 不能匹配
                            return match(s, p[:-2])
            return False
        # 遞歸解法
        return match(s, p)

思路2: 動態規劃(dp)

在這裏插入圖片描述
在這裏插入圖片描述在這裏插入圖片描述

class Solution:
   def isMatch(self, s: str, p: str) -> bool:
       length_n = len(s)
       length_p = len(p)
       dp = [[False] * (length_p+1) for _ in range(length_n+1)]
       for i in range(length_n+1):
           for j in range(length_p+1):
               # 分成空正則和非空正則兩種
               if j == 0:
                   dp[i][j] = i == 0
               else:
                   # 按照p[j]進行討論
                   if p[j-1] == '*':
                       # 不看x*
                       if j >= 2:
                           dp[i][j] |= dp[i][j-2]
                       # 看
                       if i >= 1 and (s[i-1] == p[j-2] or p[j-2] == '.'):
                           dp[i][j] |= dp[i-1][j]
                   elif i > 0 and (p[j-1] == '.' or p[j-1] == s[i-1]):
                       dp[i][j] = dp[i-1][j-1]
       return dp[length_n][length_p]

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章