LeetCode Regular Expression Matching(動態規劃)

傳送門

題意:

給你兩個字符串s和p,讓你判斷兩個字符串是否可以完全匹配.
匹配採用正則化匹配的方式,’.‘可以匹配任意字符,’*'表示前面的一個字符匹配0次或多次.

思路:

比較好想的一種方法就是遞歸.
首先p中若沒有’.‘和’’,那麼只需要看s和p是否完全一樣即可.
其次若p中有’.‘那麼只需要跳過s中和p的’.‘對應的字符,往後繼續判斷即可
最後若p中有’
'那麼它可以使它前面的字符匹配0次或者多次,這種情況我們比較好用遞歸來解決,也就是讓其匹配0次和1次進行遞歸,就會出現匹配多次的情況.

class Solution:
    def isMatch(self, s, p):
        """
        :type s: str
        :type p: str
        :rtype: bool
        """
        if not p:
        	return not s
        first_match = bool(s) and p[0] in {s[0],'.'}
        if len(p) >= 2 and p[1] == '*':
        	return (self.isMatch(s,p[2:])) or first_match and self.isMatch(s[1:],p)
        else:
        	return first_match and self.isMatch(s[1:],p[1:])

另一種方法就是動態規劃(dp),我們發現按照上面我們遞歸的方法,我們的當前狀態都是和後一步的是否匹配狀態有關的.所以我們可以設dp(i,j)表示s[i:]和p[j:]是否匹配,這樣就會減少很多不必要的遞歸.

class Solution:
    def isMatch(self, s, p):
    	mem = {}
    	def dp(i,j):
    		if (i,j) not in mem:
	    		if j == len(p):
	    			ans = i == len(s)
	    		else:
	    			match = i < len(s) and p[j] in {s[i],'.'}
		    		if j + 1 < len(p) and p[j + 1] == "*":
		    			ans = dp(i,j + 2) or (match and dp(i + 1,j))
		    		else:
		    			ans =  match and dp(i + 1,j + 1)
    			mem[i,j] = ans
    		return mem[i,j]
    	return dp(0,0)

動態規劃的另一種寫法.這個方法還是按照動態規劃的思路,這裏dp(i,j)我們表示s[:i]和p[:j]是否匹配,則:
if p[j-1]爲’.'或a-z:
dp[i][j]=dp[i1]][j1]dp[i][j] = dp[i-1]][j-1]如果s[i1]==p[j1]s[i - 1] == p[j - 1]
else:
if dp[i][j]=dp[i][j2]dp[i][j] = dp[i ][j - 2] 如果 p[j2]!=s[i1]p[j - 2] != s[i - 1]
else
dp[i][j]==dp[i][j2]dp[i][j] == dp[i][j-2] 這個代表匹配0次
dp[i][j]==dp[i][j1]dp[i][j] == dp[i][j-1] 這個代表匹配1次
dp[i][j]=dp[i1][j]dp[i][j] = dp[i-1][j] 這個代表匹配多次

class Solution:
    def isMatch(self, s, p):
    	dp = [[False] * (len(p) + 1) for _ in range(len(s) + 1)]
    	dp[0][0] = True
    	for i in range(1,len(p) + 1):
    		if p[i - 1] == "*":
    			dp[0][i] = dp[0][i - 2]
    	for i in range(1,len(s) + 1):
    		for j in range(1,len(p) + 1):
    			match = p[j - 1] in {s[i - 1],'.'}
    			if match:
    				dp[i][j] = dp[i- 1][j - 1]
    			elif j != 1 and p[j - 1] == '*':
    				if p[j - 2] not in {s[i - 1],'.'}:
    					dp[i][j] = dp[i][j] or dp[i][j - 2]
    				else:
    					dp[i][j] = dp[i][j] or dp[i - 1][j] or dp[i][j - 2] or dp[i][j - 1]
    	return dp[len(s)][len(p)]
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章