• 【LeetCode每日一题】2020.7.05 44. 通配符匹配


    44. 通配符匹配

    给定一个字符串 (s) 和一个字符模式 (p) ,实现一个支持 '?' 和 '*' 的通配符匹配。

    '?' 可以匹配任何单个字符。
    '*' 可以匹配任意字符串(包括空字符串)。

    两个字符串完全匹配才算匹配成功。

    说明:

    • s 可能为空,且只包含从 a-z 的小写字母。
    • p 可能为空,且只包含从 a-z 的小写字母,以及字符 ? 和 *。

    示例:

    输入:
    s = "aa"
    p = "a"
    输出: false
    解释: "a" 无法匹配 "aa" 整个字符串。

    输入:
    s = "aa"
    p = "*"
    输出: true
    解释: '*' 可以匹配任意字符串。

    分析:

    ​ 与10. 正则表达式匹配很像,这里贴出第10题与本题的区别:

    '*' 匹配零个或多个前面的那一个元素

    即第10题需要给出a*才能匹配aaaa,而本题只需要给出a

    这样明显降低了难度,我们不再需要考虑*之前的字符了。

    ​ 虽然之前做过第10题,还是想自己顺一遍动态规划的过程:

    1. 写出dp结构

    2. 抓住转移方程;

    3. 考虑边界条件;

    ​ 对于本题,首先考虑如何规划dp数组。假设dp[i],可以表示为s字符串的前i个字符可以被p字符串匹配,或者p字符串的前i个字符可以匹配s字符串。由于本题要求 两个字符串都要完全匹配,显然不满足要求。所以需要二重dp数组 dp[i][j],表示 s字符串前i个字符可以被p字符串前j个字符匹配

    ​ 接下来考虑转移方程,①:p[j] != '*'时,只需要考虑s[i] == p[j] or p[j] == '?'表示单个字符被匹配。

    即有:dp[i][j] == (s[i] == p[j] or p[j] == '?') and dp[i - 1][j - 1] # p[j] != "*"

    ②:如果考虑 p[j] == '*',这时有两种情况

    1. 例如:s = "abcdef", p = "abc*"

      这时*起到了匹配多个字符的作用,此时只需要考察p字符串*前的字符是否都被匹配,不断向下即可。

      dp[i][j] = dp[i - 1][j]

    2. 例如:s = "abcdef", p = "abc*def"

      *相当于空字符,直接跳过不管。

      dp[i][j] = dp[i][j - 1]

    ​ 总结:

    (dp[i][j] = egin{cases}(s[i]==p[j]) and dp[i-1][j-1] & ext{if p[j] != '*'}\ dp[i-1][j] or dp[i][j-1] & ext{if p[j] == '*'}end{cases})

    ​ 最后考虑边界条件:

    1. 如果s,p都为空,符合要求,即dp[0][0] == true
    2. 由于*可以匹配空字符,因此dp[0][j] == true if p[j] == '*' and dp[0][j - 1]

    代码(Golang):

    func isMatch(s string, p string) bool {
    	m, n := len(s), len(p)
    	dp := make([][]bool, m + 1)
    	for i := 0; i <= m; i++ {
    		dp[i] = make([]bool, n + 1)
    	}
    	dp[0][0] = true
    	for i := 0; i <= n; i++ {
    		if p[i - 1] == '*' {
    			dp[0][i] = true
    		} else {
    			break
    		}
    	}
    	for i := 1; i <= m; i++ {
    		for j := 1;j <= n; j++ {
    			if p[i - 1] == '*' {
    				dp[i][j] = dp[i][j - 1] || dp[i - 1][j]
    			} else if p[j - 1] == '?' || s[i - 1] == p[j - 1] {
    				dp[i][j] = dp[i - 1][j - 1]
    			}
    		}
    	}
    	return dp[m][n]
    }
    
  • 相关阅读:
    内存分配小问题
    从MACHINE_START开始
    Linux驱动学习(二)
    9,斐波那契数列 6,旋转数组找最小 8青蛙跳台阶 JAVA实现
    数组练习题
    类的练习
    for循环练习题
    封装练习题
    Facebook成为Apache基金会的白金赞助商
    Visual Studio 2010
  • 原文地址:https://www.cnblogs.com/enmac/p/13246787.html
Copyright © 2020-2023  润新知