leetcode - 回溯:10. Regular Expression Matching

题目:

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

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

The matching should cover the entire input string (not partial).

Note:

  • s could be empty and contains only lowercase letters a-z.
  • p could be empty and contains only lowercase letters a-z, and characters like . or *.

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 (.)".

Example 4:

Input:
s = "aab"
p = "c*a*b"
Output: true
Explanation: c can be repeated 0 times, a can be repeated 1 time. Therefore, it matches "aab".

Example 5:

Input:
s = "mississippi"
p = "mis*is*p*."
Output: false

一开始看错题了:

以为模式 aa*bc*de* 的意思是 {[(aa)*n (bc)]*n (de)}*n   【备注:*n表示 重复n遍】

然后有了如下的代码:

class Solution:
    
    def isMatch_without(self,s,p):
        match = True
        for i in range(len(s)):
            if s[i] == p[i] or p[i]==".":
                pass
            else:
                match = False
                break
        return match
    
    def isMatch(self, s: str, p: str) -> bool:
        # 边缘情况
        if s == "":
            if p == "":
                return True
            elif p[-1] == "*":
                return True
            else:
                return False
        
        match = True
        ps = str.split(p, "*")
        
        #如果不是以 * 结尾
        if ps[-1] !="":
            match = self.isMatch_without(s[-len(ps[-1]):],ps[-1])
            if match:
                s = s[:-len(ps[-1])]
            else:
                return False
                        
        ps.pop()
        index_p = len(ps)
        if index_p ==0 and s!="":
            return False
        while s!="":
            if index_p>0:
                index_p -=1
            else:
                index_p = len(ps)-1
            if len(s) >= len(ps[index_p]):
                match = self.isMatch_without(s[-len(ps[index_p]):],ps[index_p])
            else:
                match = False
            if match:
                while match & (s!=""):
                    s = s[:-len(ps[index_p])]
                    if len(s) >= len(ps[index_p]):
                        match = self.isMatch_without(s[-len(ps[index_p]):],ps[index_p])
                    else:
                        match = False
            else:
                index_p = len(ps) - 1
                if len(s) >= len(ps[index_p]):
                    match = self.isMatch_without(s[-len(ps[index_p]):],ps[index_p])
                else:
                    match = False
                if not match:
                    return False
                else:
                    while match & (s!=""):
                        s = s[:-len(ps[index_p])]
                        if len(s) >= len(ps[index_p]):
                            match = self.isMatch_without(s[-len(ps[index_p]):],ps[index_p])
                        else:
                            match = False
        return True
                
        

结果发现题目没有那么复杂,

模式为 aa*bc*de*的意思是: 

a (a)*n b (c)*n d (e)*n  ,如此一来,这个变成了一个回溯题。对于 x* 模式需要分两步:

1、s不删x(x在s中重复0遍),模式p删除 x*判断能否走通;

2、若走不通 s中删除 x,模式p保留 x*判断能否走通(通过不断回溯,可以实现 s中删除 n遍x,p中删除 x*)

class Solution:
    
    def isMatch(self, s: str, p: str) -> bool:
        i = len(p)-1
        while i >=0:
            if p[i] == "*":
                i -= 1

                # 假设s中不包含 * 前面的字符,尝试看是否走得通
                if self.isMatch(s,p[:i]):
                    return True

                # 走不通,回溯,看能否删一个字符
                else:
                    while len(s)>0:
                        if p[i]=="." or s[-1]==p[i]:
                            s = s[:-1]
                            if self.isMatch(s,p[:i]):
                                return True
                        else:
                            i -= 1
                            break

            # 不含*的普通模式,没有分枝
            else:
                if len(s)>0:
                    if p[i]=="." or s[-1]==p[i]:
                        i -= 1
                        s = s[:-1]
                    else:
                        return False
                else:
                    return False
                
        if len(s) ==0:
            return True
        else:
            return False
                
                       

这个题必须用回溯,不用回溯,会有特别多边边角角的问题考虑不到。

发布了45 篇原创文章 · 获赞 1 · 访问量 3383

猜你喜欢

转载自blog.csdn.net/qq_22498427/article/details/104437940