代码动态规划:
- dp[i][j] 数组用来表示 s 的前 i 个字符,和 p 的前 j 个字符是否匹配
- 状态转移方程:如果 p 当前字符为字母且与 s 的当前字母相等,则状态转移
dp[i][j] = dp[i-1][j-1] - 如果 p 当前不是字母,是 '?' ,显然状态转移与步骤2中的情况一样
- 如果 p 当前是
*,那么我们需要考虑,是否计算当前这个星号,如果不考虑则状态转移dp[i][j] = dp[i][j-1] - 如果考虑则状态转移
dp[i][j] = dp[i-1][j],即与上一层的dp结果一样,因为星号可以延长
状态转移方程:
- 其他情况中的false我们可以忽略,因为我们创建dp数组时默认全为false
- 最后考虑临界情况,也就是在状态转移时 i,j 会出现 0 的情况,也就是dp数组中的第一排,和第一列,
- dp[0][0]显然为true,即都为空串时对应的dp
- 第一排用来表示s为空串对应的dp值,第一列p为空串对应的dp值
- p为空串自然为false
- s为空串时,如果p出现连续的星号则当前对应的dp值为true,当出现第一个字符后,之后的值皆为false
func isMatch(s string, p string) bool {
n := len(s)
m := len(p)
dp := make([][]bool, n+1)
for i := range dp {
dp[i] = make([]bool, m+1)
}
for i,v := range p {
if v != '*' {
break
}
dp[0][i+1] = true
}
dp[0][0] = true
for i := 1; i <= n; i++ {
for j := 1; j <= m; j++ {
if p[j-1] == s[i-1] || p[j-1] == '?' {
dp[i][j] = dp[i-1][j-1]
}else if p[j-1] == '*' {
dp[i][j] = dp[i][j-1] || dp[i-1][j]
}
}
}
return dp[n][m]
}