44-Wildcard Matching

Description

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

问题描述

给定字符串s和p,实现支持通配符”?”和”*”的匹配

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

匹配需要针对整个字符串,而不是部分。


问题分析

两种做法,dfs + memorization 和 贪心


解法1(dfs + memorization)

/*
dp[i][j]记录s.substring(i)和p.substring(j)是否匹配

如果只有"?", 那么很好办,一个一个匹配就可以了
加上"*", 有两种选择, "*"匹配 或者 "*" 不匹配
匹配, backTrack(s, p, i + 1, j, dp))
不匹配, backTrack(s, p, i, j + 1, dp)
*/
class Solution {
    private enum Result{
        TRUE,FALSE
    }
    public boolean isMatch(String s, String p) {
        int len1 = s.length(), len2 = p.length();

        Result[][]dp = new Result[len1 + 1][len2 + 1];

        return backTrack(s, p, 0, 0, dp);
    }
    public boolean backTrack(String s, String p, int i, int j, Result[][] dp){
        if(dp[i][j] != null)    return dp[i][j] == Result.TRUE;

        boolean res = false;
        if(j == p.length()) res = (i == s.length());
        else{
            if(p.charAt(j) == '*'){
                res = backTrack(s, p, i, j + 1, dp) || (i < s.length() && backTrack(s, p, i + 1, j, dp));
            }else{
                boolean firstMatch = i < s.length() && (s.charAt(i) == p.charAt(j) || p.charAt(j) == '?');
                res = firstMatch && backTrack(s, p, i + 1, j + 1, dp);
            }
        }
        dp[i][j] = res ? Result.TRUE : Result.FALSE;

        return res;
    }
}

解法2(贪心)

class Solution {
    public boolean isMatch(String s, String p) {
        //starj记录上一个"*"的位置
        //match记录与"*"匹配的i的位置(与starj不同的是,每次回溯,match自增)
        int i = 0, j = 0, starj = -1, match = 0;

        while(i < s.length()){
            //字符相等或者p.charAt(j) == '?'
            if(j < p.length() && (s.charAt(i) == p.charAt(j) || p.charAt(j) == '?')){
                i++;
                j++;
            //遇到'*', 记录'*'的位置,并记录starj和match
            }else if(j < p.length() && p.charAt(j) == '*'){
                starj = j;
                j++;
                match = i;
            //不是上述两种情况,无法匹配,因此回溯
            //注意,若出现第二个'*', 会对之前的覆盖,因为已经不需要用之前的"*"进行回溯了
            }else if(starj != -1){
                j = starj + 1;
                match++;
                i = match;
            //其他情况, 直接返回false
            }else{
                return false;
            }
        }
        //清除'*'
        while(j < p.length() && p.charAt(j) == '*') j++;
        //若p清空,说明匹配
        return j == p.length();
    }
}

猜你喜欢

转载自blog.csdn.net/LaputaFallen/article/details/80055351