给你一个字符串 s
和一个字符规律 p
,请你来实现一个支持 '.'
和 '*'
的正则表达式匹配。
所谓匹配,是要涵盖 整个 字符串 s
的,而不是部分字符串。
而这仅仅是匹配了我们的前前个字符,并不能覆盖所有的情况,因为如果我们的当前正则表达式的*前面一个字符刚好能够匹配当前需要被匹配的字符串(s),这确实无法通过上面那一步判断出来的,所以还需要加一步判断。
func isMatch(s string, p string) bool {
m, n := len(s), len(p)
f := make([][]bool, m + 1)
for i := 0; i <= m; 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] == '*' {
//为什么是j - 2?
//因为'x*'可以匹配0个或者任意一个'x'
//所以只需要前前一个匹配即可
f[i][j] = f[i][j] || f[i][j - 2]
if match(i, j - 1, s, p) {
//当然,如果和'*'前一个字符匹配,也是一种情况
//此时就应该是i - 1,而不是i了
f[i][j] = f[i][j] || f[i - 1][j]
}
} else if match(i, j, s, p) {
//如果匹配,根据前一个状态转移
f[i][j] = f[i][j] || f[i - 1][j - 1]
}
}
}
return f[m][n]
}
//这里是i或者j - 1的原因是我们的dp对应的 数组第0位被占用,所以
//向后移了一位。对应到字符串上,则需要减回去
func match(i, j int, s, p string) bool {
if i == 0 {
return false
}
if p[j - 1] == '.' {
return true
}
return s[i - 1] == p[j - 1]
}
func isMatch(s string, p string) bool {
n, m := len(s), len(p)
f := make([][]bool, n + 1)
for i := 0; i <= n; i ++ {
f[i] = make([]bool, m + 1)
}
f[0][0] = true
for i := 0; i <= n; i ++ {
for j := 1; j <= m; j ++ {
if p[j - 1] == '*' {
f[i][j] = f[i][j - 2] || f[i][j]
if i > 0 && (p[j - 2] == '.' || s[i - 1] == p[j - 2]) {
f[i][j] = f[i - 1][j] || f[i][j]
}
} else if i > 0 && (s[i - 1] == p[j - 1] || p[j - 1] == '.') {
f[i][j] = f[i - 1][j - 1] || f[i][j]
}
}
}
return f[n][m]
}