1.回溯法
思路:
首先考虑如果模式串中没有 * 号,那么我们只需要从左向右检查模式串每个字符是否能匹配匹配串中的每一个字符。在匹配字符时,如果当前模式串中字符为 . 或者与匹配串对应字符相等均为通过。
例如:
匹配串为:abc 模式串为: a.c 从左向右匹配,返回true
接下来讨论如果模式串中有 * 号,那么我们可以利用回溯的方法,来根据不同的情况对两个字符串切分进行子串的匹配。切分后的模式串如果有*号一般在第二位,这里有两种情况:①如果*号后面的模式串能够和匹配串匹配的话,那么直接返回true。②如果模式串第一位和匹配串第一位相等,并且匹配串去除第一位后面子串能够和模式串匹配的话,返回true。
例如:
匹配串为:s = abbbc 模式串为:p = ab*c
p[1] != * , s[1] == p[1] , 则 s= s[1:] = bbbc , p = p[1:] = b*c , 继续匹配 s 和 p
p[1] ==* , 此时 p[2:] = c , s = bbbc 不匹配。又s[0] = p[0] = b,则若s=s[1:] = bbc 能够匹配 p = b*c的话,返回true
p[1] ==* , 此时 p[2:] = c , s = bbc 不匹配。又s[0] = p[0] = b,则若s=s[1:] = bc 能够匹配 p = b*c的话,返回true
p[1] ==* , 此时 p[2:] = c , s = bc 不匹配。又s[0] = p[0] = b,则若s=s[1:] = c 能够匹配 p = b*c的话,返回true
p[1] ==* , 此时 p[2:] = c , s = c 匹配,则返回true
代码:
class Solution(object): def isMatch(self, text, pattern): if not pattern: return not text first_match = bool(text) and pattern[0] in {text[0], '.'} if len(pattern) >= 2 and pattern[1] == '*': return (self.isMatch(text, pattern[2:]) or first_match and self.isMatch(text[1:], pattern)) else: return first_match and self.isMatch(text[1:], pattern[1:])
2.动态规划
思路:
通过用dp(i,j)表示text[i:]和pattern[j:]能否匹配。这里同样采用回溯的方法,通过判断子字符串是否匹配,来判断当前字符串的匹配情况。
例如:
判断dp[i][j]
①若pattern[j+1]=='*',则若dp[i][j+2]==true或者text[i]==pattern[j]并且dp[i+1][j]==ture时,返回true
②若pattern[j+1]!='*',则若text[i]==pattern[j]并且dp[i+1][j+1]==ture时,返回true
代码:
class Solution(object): def isMatch(self, text, pattern): memo = {} def dp(i, j): if (i, j) not in memo: if j == len(pattern): ans = i == len(text) else: first_match = i < len(text) and pattern[j] in {text[i], '.'} if j+1 < len(pattern) and pattern[j+1] == '*': ans = dp(i, j+2) or first_match and dp(i+1, j) else: ans = first_match and dp(i+1, j+1) memo[i, j] = ans return memo[i, j] return dp(0, 0)
如