006_正则表达式匹配
知识点:递归、动态规划、正则表达式
LeetCode第十题:https://leetcode-cn.com/problems/regular-expression-matching/submissions/
大多数情况下,递归、DFS和回溯这三者在思想上是差不多等价的,都是暴力枚举的思路。配合上状态变量(一维、二维甚至三维数组),保存中间过程(重叠子问题)的解,就可以形成动态规划的基本形式了。
语言:GoLang
// 动态规划优化:递归
var memo map[[2]int]bool
func isMatch(s string, p string) bool {
memo = map[[2]int]bool{}
return dp(s, p, 0, 0)
}
func dp(s string, p string, i int, j int) bool {
if j == len(p) {
return i == len(s)
}
key := [2]int{i, j}
if value, ok := memo[key]; ok {
return value
}
firstMatch := i < len(s) && (s[i] == p[j] || p[j] == '.')
if j + 1 < len(p) && p[j + 1] == '*' {
memo[key] = dp(s, p, i, j + 2) || (firstMatch && dp(s, p, i + 1, j))
}else {
memo[key] = firstMatch && dp(s, p, i + 1, j + 1)
}
return memo[key]
}
// 朴素解法:递归,可以了解正则的基本形式
func isMatch_(s string, p string) bool {
if len(p) == 0 {
return len(s) == 0
}
firstMatch := len(s) != 0 && (s[0] == p[0] || p[0] == '.')
if len(p) > 1 && p[1] == '*' {
// 略过当前的"字符*"组合,即不匹配 || 先匹配它一次,第二次与否交给下一层递归来决定
return isMatch(s, p[2:]) || (firstMatch && isMatch(s[1:], p))
}else {
return firstMatch && isMatch(s[1:], p[1:])
}
}