正则表达式:
正则表达式(regular expression)就是用一个“字符串”来描述一个特征,然后去验证另一个“字符串”是否符合这个特征。比如 表达式“ab+” 描述的特征是“一个 'a' 和 任意个 'b' ”,那么 'ab', 'abb', 'abbbbbbbbbb' 都符合这个特征。
常用的正则表达式符号如下表所示:
其中最常用的有如下几个符号:
“ \ ”: 可以作为转义字符,如我们平常编程时的转义字符类似,主要时解决匹配特殊字符集,
“\w” : 匹配单词字符
“ ^ ”: 表示取反。 如:[^\w] 表示非单词字符。但是要想匹配'^'符号,我们需要用转义字符:[^]
"+","?","*": 分别表示匹配前一个字符 大于0次,大于等于0次,0次或1次
“{m}”: 表示匹配前面字符m次
“$”: 表示匹配末尾串
“[\u4e00-\u9fa5]?”: 匹配所有的汉子字符,故[^\u4e00-\u9fa5]?:匹配所有非汉字字符,用于标点的剔除
其中考察我们编程实现的有四个符号: [. * ? +]。 主要写出函数:
boolean isMatch(String a, String p)
;其中p为模式串,a为匹配串思路1 :backtracking:
“*” 表示前面的字符出现>=0 次,所以以*之前的点为回溯点。利用递归的思路程序如下:
class Solution(object):
cache = {}
def isMatch(self, s, p):
if (s, p) in self.cache:
return self.cache[(s, p)]
if not p:
return not s
if p[-1] == '*':
if self.isMatch(s, p[:-2]):
self.cache[(s, p)] = True
return True
if s and (s[-1] == p[-2] or p[-2] == '.') and self.isMatch(s[:-1], p):
self.cache[(s, p)] = True
return True
if s and (p[-1] == s[-1] or p[-1] == '.') and self.isMatch(s[:-1], p[:-1]):
self.cache[(s, p)] = True
return True
self.cache[(s, p)] = False
return False
思路2:DP
建立二维dp数组;其中dp[i+1][j+1] 表示字符s[0.....i]与字符p[0...j]相互匹配;所以我们关注p[j + 1]的字符是否为‘*’作为我们讨论的分类
p[j + 1] != '*': 只需要p[j + 1] == '.' || p[j + 1] == s[i + 1]时 dp[i+1][j = 1] =dp[i][j]
p[j + 1] == '*': 我们需要看前j个是否已经匹配了s[0...i]: 匹配了就让*为不出现字符。否则看如果p[i] == '.' || p[i] == s[i] 则可以让其等于一个前方字符
def isMatch(self, s, p):
dp = [[False] * (len(s) + 1) for _ in range(len(p) + 1)]
dp[0][0] = True
for i in range(1, len(p)):
dp[i + 1][0] = dp[i - 1][0] and p[i] == '*'
for i in range(len(p)):
for j in range(len(s)):
if p[i] == '*':
dp[i + 1][j + 1] = dp[i - 1][j + 1] or dp[i][j + 1]
if p[i - 1] == s[j] or p[i - 1] == '.':
dp[i + 1][j + 1] |= dp[i + 1][j]
else:
dp[i + 1][j + 1] = dp[i][j] and (p[i] == s[j] or p[i] == '.')
return dp[-1][-1]