【LeetCode】解题44:Wildcard Matching(动态规划解法)

LeetCode解题 44:Wildcard Matching(动态规划解法)

Problem 44: Wildcard Matching [Hard]

Given an input string (s) and a pattern (p), implement wildcard pattern matching with support for '?' and '*'.

'?' Matches any single character.
'*' Matches any sequence of characters (including the empty sequence).

The matching should cover the entire input string (not partial).

Note:

  • s could be empty and contains only lowercase letters a-z.
  • p could be empty and contains only lowercase letters a-z, and characters like ?or *.

Example 1:

Input:
s = “aa”
p = “a”
Output: false
Explanation: “a” does not match the entire string “aa”.

Example 2:

Input:
s = “aa”
p = “*”
Output: true
Explanation: ‘*’ matches any sequence.

Example 3:

Input:
s = “cb”
p = “?a”
Output: false
Explanation: ‘?’ matches ‘c’, but the second letter is ‘a’, which does not match ‘b’.

Example 4:

Input:
s = “adceb”
p = “*a*b”
Output: true
Explanation: The first ‘*’ matches the empty sequence, while the second ‘*’ matches the substring “dce”.

Example 5:

Input:
s = “acdcb”
p = “a*c?b”
Output: false

来源:LeetCode

解题思路

题解10:Regular Expression Matching,使用动态规划思想。维护数组match[n][m],match[i][j]代表字符串s的前i个和模式p的前j个是否匹配。二重循环遍历sp,match[i][j]根据p[j]和s[i]的关系可以由match[i-1][j-1]等前项转换而来,具体转换公式为:

  1. p [ j ] = s [ i ] p[j] = s[i] p[j]=s[i] 或者 p [ j ] = p[j] = p[j]= '?'时,有
    m a t c h [ i ] [ j ] = m a t c h [ i − 1 ] [ j − 1 ] match[i][j] = match[i-1][j-1] match[i][j]=match[i1][j1]

  2. p [ j ] = p[j] = p[j]= '*'时,*有可能匹配零个字符或多个字符。假设当前s###p###*,则match[i][j]有可能从不同的前项转移而来:

    i. *匹配多个字符的情况,例如:czhcb|aczh|*。此时s[i]上的a只是*的延续,转移公式为:
    m a t c h [ i ] [ j ] = m a t c h [ i − 1 ] [ j ] match[i][j] = match[i-1][j] match[i][j]=match[i1][j]
    注意:除了上述例子中*匹配了三个字符cba的情况,转移公式同样适用于匹配一个字符的情况。(s = czhcb|a,p = czhcb|*,match[i-1][j]代表czhcbczhcb*匹配,多一个a后仍然相当于a只是*的延续,因此不需要特意考虑match[i-1][j-1]的值。)

    ii. *匹配零个字符的情况,例如:czh|aczha|*。此时*是多余的,可以去掉,转移公式为:
    m a t c h [ i ] [ j ] = m a t c h [ i ] [ j − 1 ] match[i][j] = match[i][j-1] match[i][j]=match[i][j1]
    情况i和情况ii中,只要任意一个能匹配上,则 m a t c h [ i ] [ j ] = t r u e match[i][j] = true match[i][j]=true

  3. p [ j ] p[j] p[j]不属于上述任何情况,即 p [ j ] p[j] p[j]不为特殊符号且 p [ j ] ≠ s [ i ] p[j] \neq s[i] p[j]=s[i]时, m a t c h [ i ] [ j ] = f a l s e match[i][j] = false match[i][j]=false

时间复杂度为 O ( n m ) O(nm) O(nm),空间复杂度为 O ( n m ) O(nm) O(nm)

运行结果:
在这里插入图片描述

要点:动态规划

Solution (Java)

class Solution {
    public boolean isMatch(String s, String p) {
        int n = s.length() + 1;
        int m = p.length() + 1;
        if(n == 1 && m == 1) return true;
        if(n > 1 && m == 1) return false;
        boolean[][] match = new boolean[n][m];
        // initialize
        match[0][0] = true;
        for(int mj = 1; mj < m; mj++){
            int j = mj - 1;
            if(p.charAt(j) == '*') match[0][mj] = match[0][mj-1];
            else match[0][mj] = false;
        }
        for(int mi = 1; mi < n; mi++){
            match[mi][0] = false;
        }
        // dp
        for(int mi = 1; mi < n; mi++){
            for(int mj = 1; mj < m; mj++){
                int i = mi - 1;
                int j = mj - 1;
                if(p.charAt(j) == s.charAt(i) || p.charAt(j) == '?'){
                    match[mi][mj] = match[mi-1][mj-1];
                }
                else if(p.charAt(j) == '*'){
                    match[mi][mj] = match[mi-1][mj] || match[mi][mj-1];
                }
                else{
                    match[mi][mj] = false;
                }
            }
        }
        return match[n-1][m-1];
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值