10. 正则表达式匹配
解题思路
- 1、设定
memo[indexStr][j]
为s
取前indexStr
个字符,p
取前indexPattern
个字符时,是否匹配 - 2、当
s[indexStr]
和p[indexPattern]
匹配时,那么其结果继承前一项,即memo[indexStr-1][indexPattern-1]
那么怎么判断两边匹配呢? 当p[indexPattern] == s[indexStr]
,即两者字符一样,或者p[indexPatter]
为.
时,两边匹配,所以咱们可以写出这个方法,来判断匹配
// 字符串s和正则p当前元素是否匹配
matches := func(sIndex, pIndex int) bool {
if sIndex < 1 {
return false
}
if p[pIndex-1] == '.' || s[sIndex-1] == p[pIndex-1] {
return true
}
return false
}
- 3、当
s[indexStr]
和p[indexPattern]
不匹配时,就看p[indexPattern]
是不是*
号,这时候,分两种情况,一种是- 1)
s: ab p: abc*
这种,虽然p
里面有c*
,但是s
里面可以一个c都没有,因为*
可以匹配0个字符,那么匹配可以直接跳过p
的最后两项
- 1)
- memo[indexStr][indexPattern] = memo[indexStr][indexPattern-2]
- 2)
abbb / ab.*
或abbb / abb*
这种,这时候,因为不知道到底能匹配多少个b
,所以可以把结果托给前一项,即
- 2)
- memo[indexStr][indexPattern] = memo[indexStr-1][indexPattern]
- 3)
abbb / ac.*
这种,直接不匹配了,因为memo对应项的值默认就是false,咱们可以不处理了
- 3)
- 4、注意base项,当indexStr/indexStr都是0时候,肯定匹配咯
func isMatch(s string, p string) bool {
m, n := len(s), len(p)
dp := make([][]bool,len(s)+1)
for i:=0;i<=m;i++ {
dp[i] = make([]bool,n+1)
}
dp[0][0] = true
for i := 0;i <= m; i++ {
for j := 1;j <= n; j++ { //防止其越界,从1开始
if p[j-1] == '*' {
if i!=0 && (s[i-1] == p[j-2] || p[j-2] == '.') {
dp[i][j] = dp[i][j] || dp[i][j-2] || dp[i-1][j] || dp[i-1][j-2]
} else {
dp[i][j] = dp[i][j] || dp[i][j-2] //前一个字符没有匹配上,直接匹配零个
}
} else if i != 0 && (s[i-1] == p[j-1] || p[j-1] == '.') {
dp[i][j] = dp[i][j] || dp[i-1][j-1] //前一个字符匹配相同,或者模式为.时,只匹配一个字符
}
}
}
return dp[m][n]
}
//二维,时空Omn
func isMatch(s string, p string) bool {
m, n := len(s), len(p)
matches := func(i, j int) bool {
if i == 0 {
return false
}
if p[j-1] == '.' {
return true
}
return s[i-1] == p[j-1]
}
f := make([][]bool, m + 1)
for i := 0; i < len(f); i++ {
f[i] = make([]bool, n + 1)
}
f[0][0] = true
for i := 0; i <= m; i++ {
for j := 1; j <= n; j++ {
if p[j-1] == '*' {
f[i][j] = f[i][j] || f[i][j-2]
if matches(i, j - 1) {
f[i][j] = f[i][j] || f[i-1][j]
}
} else if matches(i, j) {
f[i][j] = f[i][j] || f[i-1][j-1]
}
}
}
return f[m][n]
}