动态规划|通配符匹配

题目描述

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

'?' 可以匹配任何单个字符。
'*' 可以匹配任意字符串(包括空字符串)。
两个字符串完全匹配才算匹配成功。

说明:

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

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

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

输入:
s = "cb"
p = "?a"
输出: false
解释: '?' 可以匹配 'c', 但第二个 'a' 无法匹配 'b'。
示例 4:

输入:
s = "adceb"
p = "ab"
输出: true
解释: 第一个 '' 可以匹配空字符串, 第二个 '' 可以匹配字符串 "dce".
示例 5:

输入:
s = "acdcb"
p = "a*c?b"
输入: false

解题思路

关键在于有个 * ,它是可以匹配任意的字符的,那么在匹配的过程中无法确切地知道,该次匹配之后p的索引是否应该移到下一个位置。为了解决这个问题,就可以考虑记录下匹配状态,然后当前的匹配状态,就可以由之前的状态推导得到。
设置一个数组 dp[i][j],记录s的前i个和p的前j的匹配情况。
然后分以下几种情况讨论状态的转移情况

  1. s[i]==p[j] ||p[j]=='?',那么 dp[i][j] = dp[i-1][j-1]
  2. 否则,如果,p[j]=='',因为,可以匹配零个以上的字符,
    2.1 如果,dp[i][j-1]是匹配的,那么当前的也一定匹配,(不匹配任何字符的情况)
    2.2 如果,dp[i-1][j-1] 是匹配的,那么当前的也一定匹配,
    匹配一个字符的情况
    2.3 如果,dp[i-1][j] 是匹配的, 那么当前的也一定匹配,这个的意思的是*匹配了多个字符,那么现在再多匹配一个也是可以的。

动态规划问题还有一个注意的问题就是状态的初始化。这里用dp[0][0]表示空配空,然后就是初始化一下s为空,p非空的情况

Java 代码如下,注意java布尔数组的默认值为false的。

public boolean isMatch(String s, String p) {
        int n = s.length();
        int m = p.length();
        boolean [][]dp = new boolean[n+1][m+1];
        dp[0][0] = true;
        for(int i=0;i<m;i++){
            if(p.charAt(i)=='*'&&dp[0][i])
                dp[0][i+1] = true;
        }

        for(int i = 0;i<n;i++){
            for(int j = 0;j<m;j++){
                if(s.charAt(i)==p.charAt(j)||p.charAt(j)=='?')
                    dp[i+1][j+1] = dp[i][j];
                else if(p.charAt(j)=='*'){
                    dp[i+1][j+1] = dp[i+1][j]||dp[i][j+1]||dp[i][j];
                }
            }
        } 
        return dp[n][m];


    }
全部评论

相关推荐

评论
点赞
收藏
分享

创作者周榜

更多
牛客网
牛客网在线编程
牛客网题解
牛客企业服务