首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >通配符匹配

通配符匹配

作者头像
你的益达
发布2020-08-05 15:34:28
2.5K0
发布2020-08-05 15:34:28
举报

问题描述:

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

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

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

示例 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 = "*a*b"
输出: true
解释: 第一个 '*' 可以匹配空字符串, 第二个 '*' 可以匹配字符串 "dce".
示例 5:

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

来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/wildcard-matching
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。

递归

首先定义fun(i,j)返回s从 i 开始,p从 j 开始能否匹配的上。

对当前元素s[i] 和 p[j] 分情况讨论,

若s[i] 恰好等于p[j],或者p[j]为 ‘?’时,fun(i, j)的求解就可以转化为对 fun(i + 1, j + 1)的求解;

若p[i]即不为’?’ ‘*’这些,又不等于s[i],s从i开始p从j开始无论如何也匹配不上;

剩下就只有p[j] 为 ’*‘这种可能了,依次让p[j] 匹配0个,1个,2个….k个,fun(i, j)的求解就可以转化为求解一系列的fun(i + k, j + 1)的值。

递归的出口:

当p已经没了,但是s还有,该情况无论如何也匹配不上了,返回false;

当p和s都没了 返回true;

当s没了p还有,该情况下只有p的后续全为’*’才能匹配上。

实现代码如下:

class Solution {
    public boolean isMatch(String s, String p) {
        return process(s.toCharArray(), p.toCharArray(), 0, 0);
    }
    public boolean process(char[] s, char[] p, int i, int j){
        if(j == p.length){
            return i == s.length;
        }
        if(i == s.length){
            return p[j] == '*' && process(s, p, i, j + 1);
        }
        if(p[j] == '?' || p[j] == s[i]){
            return process(s, p, i + 1, j + 1);
        }
        if(p[j] != '*'){ 
            return false;
        }
        // p[j] == '*';
        for(int k = 0; i + k <= s.length; k++){
            if(process(s, p, i + k, j + 1)){
                return true;
            }
        }
        return false;
    }
}

动态规划

将上述递归解法改成动态规划,

定义dp 为(M + 1) * (N + 1)的布尔型数组,dp[i] [j] 为s从 i 开始,p从 j 开始能否匹配上,其中M为s的长度,N为p的长度。

转移函数:

dp[i][j] = \begin{cases}dp[i + 1][j + 1] \qquad\qquad\qquad\qquad\qquad\qquad\qquad\qquad\qquad\qquad s[i] = p[j]或p[j] = ?\\\ dp[i+0][j+1]||dp[i+1][j+1]||dp[i+2][j+1]….||dp[M][j+1]\qquad p[j] = *\\\ false\qquad\qquad\qquad\qquad\qquad\qquad\qquad\qquad\qquad\qquad\qquad\qquad\qquad\qquad eles\end{cases}

baseline:

dp[M][N]= true
dp[i][N] = false \qquad i< M
dp[M][j]=\begin{cases}true \qquad \qquad p[j] = * , p[j + 1]= * , … p[N - 1] = *\\\false \qquad \qquad else\end{cases}

实现代码如下:

class Solution {
    public boolean isMatch(String s, String p) {
        char[] arrS = s.toCharArray();
        char[] arrP = p.toCharArray();
        int M = arrS.length;
        int N = arrP.length;
         // dp[i][j] s以i开头, p 以j开头能否匹配上
        boolean[][] dp = new boolean[M + 1][N + 1]; 
        dp[M][N] = true;
        for(int j = N - 1; j >= 0; j--){
            if(arrP[j] == '*'){
                dp[M][j] = true;
            }else{
                break;
            }
        }
        for(int i = M - 1; i >= 0; i--){
            for(int j = N - 1; j >= 0; j--){
                if(arrP[j] == '?' || arrS[i] == arrP[j]){
                    dp[i][j] = dp[i + 1][j + 1];
                }else if(arrP[j] == '*'){
                    for(int k = 0; i + k <= M; k++){
                        if(dp[i + k][j + 1]){
                            dp[i][j] = true;
                            break;
                        }
                    }
                }
            }
        }
        return dp[0][0];
    }
 }

该算法的时间复杂度为O(N* M ^2)。

优化后的DP

我们发现求解dp[i] [j]当p[j]为’*’时,需要从当前行(i行)开始对右边一列(dp[i] [j + 1] … dp[M] [j + 1])进行或运算,我们发现dp[i + 1] [j]的求解也是从当前行(i + 1行)为从dp[i + 1 ] [j + 1] … dp[M] [j + 1],因此优化后的转移函数如下:

dp[i][j] = \begin{cases}dp[i + 1][j + 1] \qquad\qquad s[i] = p[j]或p[j] = ?\\\ dp[i][j+1]||dp[i+1][j]\qquad p[j] = *\\\ false\qquad\qquad\qquad\qquad\qquad eles\end{cases}

实现代码如下:

    public boolean isMatch(String s, String p) {
        char[] arrS = s.toCharArray();
        char[] arrP = p.toCharArray();
        int M = arrS.length;
        int N = arrP.length;
         // dp[i][j] s以i开头, p 以j开头能否匹配上
        boolean[][] dp = new boolean[M + 1][N + 1]; 
        dp[M][N] = true;
        for(int j = N - 1; j >= 0; j--){
            if(arrP[j] == '*'){
                dp[M][j] = true;
            }else{
                break;
            }
        }
        for(int i = M - 1; i >= 0; i--){
            for(int j = N - 1; j >= 0; j--){
                if(arrP[j] == '?' || arrS[i] == arrP[j]){
                    dp[i][j] = dp[i + 1][j + 1];
                }else if(arrP[j] == '*'){
                    dp[i][j] = dp[i + 1][j] || dp[i][j + 1];
                }
            }
        }
        return dp[0][0];
    }

时间复杂度为O(N * M)。

本文参与 腾讯云自媒体分享计划,分享自作者个人站点/博客。
原始发表:2020-07-05,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 问题描述:
  • 递归
  • 动态规划
  • 优化后的DP
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档