通配符匹配——动态规划

115 阅读2分钟

image.png

代码动态规划:

  1. dp[i][j] 数组用来表示 s 的前 i 个字符,和 p 的前 j 个字符是否匹配
  2. 状态转移方程:如果 p 当前字符为字母且与 s 的当前字母相等,则状态转移 dp[i][j] = dp[i-1][j-1]
  3. 如果 p 当前不是字母,是 '?' ,显然状态转移与步骤2中的情况一样
  4. 如果 p 当前是 * ,那么我们需要考虑,是否计算当前这个星号,如果不考虑则状态转移 dp[i][j] = dp[i][j-1]
  5. 如果考虑则状态转移 dp[i][j] = dp[i-1][j],即与上一层的dp结果一样,因为星号可以延长

状态转移方程

image.png

  1. 其他情况中的false我们可以忽略,因为我们创建dp数组时默认全为false
  2. 最后考虑临界情况,也就是在状态转移时 i,j 会出现 0 的情况,也就是dp数组中的第一排,和第一列,
  3. dp[0][0]显然为true,即都为空串时对应的dp
  4. 第一排用来表示s为空串对应的dp值,第一列p为空串对应的dp值
  5. p为空串自然为false
  6. 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]
}