https://www.lintcode.com/problem/wildcard-matching/description
给定一个字符串 s s s和一个模式串 p p p, p p p中含字母,'?'或者'*'。其中'?'可以匹配任何单个字符,'*'可以匹配任意字符串,包括空串。问 s s s是否符合 p p p所代表的模式。
该题的思考方式与Regular Expression Matching这个问题非常相似,可以参考https://blog.csdn.net/qq_46105170/article/details/109213897。下面详细说明。
思路是动态规划。设 f [ i ] [ j ] f[i][j] f[i][j]是 s s s的前 i i i个字符和 p p p的前 j j j个字符是否匹配( i i i和 j j j从 1 1 1开始计数),即 s [ 0 : i − 1 ] s[0:i-1] s[0:i−1]是否和 p [ 0 : j − 1 ] p[0:j-1] p[0:j−1]匹配。那么可以按照 p [ j − 1 ] p[j-1] p[j−1]的匹配方式来分类: 1、如果 p [ j − 1 ] p[j-1] p[j−1]不是'*',那必然有 s [ 0 : i − 1 ] s[0:i-1] s[0:i−1]非空,并且要么 s [ i − 1 ] = p [ j − 1 ] s[i-1]=p[j-1] s[i−1]=p[j−1], p [ j − 1 ] p[j-1] p[j−1]是'?'。这样 p p p最后一个字符匹配好之后,还需要 s [ 0 : i − 2 ] s[0:i-2] s[0:i−2]与 p [ 0 : j − 2 ] p[0:j-2] p[0:j−2]也要匹配。所以有: f [ i ] [ j ] = ( s [ i − 1 ] = p [ j − 1 ] ∨ p [ j − 1 ] = ? ) ∧ f [ i − 1 ] [ j − 1 ] f[i][j]=(s[i-1]=p[j-1]\lor p[j-1]=?)\land f[i-1][j-1] f[i][j]=(s[i−1]=p[j−1]∨p[j−1]=?)∧f[i−1][j−1]2、如果 p [ j − 1 ] p[j-1] p[j−1]是'*',那么这个'*'有两种匹配方式,一种是匹配空串,那么能匹配当前仅当 s [ 0 : i − 1 ] s[0:i-1] s[0:i−1]与 p [ 0 : j − 2 ] p[0:j-2] p[0:j−2]能匹配,也就是看 f [ i ] [ j − 1 ] f[i][j-1] f[i][j−1];另一种是匹配非空串,那么将 s [ i − 1 ] s[i-1] s[i−1]删掉之后需要继续和 p [ 0 : j − 1 ] p[0:j-1] p[0:j−1]匹配,即需要 s [ 0 : i − 2 ] s[0:i-2] s[0:i−2]和 p [ 0 : j − 1 ] p[0:j-1] p[0:j−1]要匹配,也就是看 f [ i − 1 ] [ j ] f[i-1][j] f[i−1][j]。所以有: f [ i ] [ j ] = f [ i ] [ j − 1 ] ∨ f [ i − 1 ] [ j ] f[i][j]=f[i][j-1]\lor f[i-1][j] f[i][j]=f[i][j−1]∨f[i−1][j]接下来考虑初始条件,首先空串可以和空模式匹配,但非空串不能喝空模式匹配,所以有 f [ 0 ] [ 0 ] f[0][0] f[0][0]是true,但当 i > 0 i>0 i>0,则 f [ i ] [ 0 ] f[i][0] f[i][0]是false。而空串是否能匹配非空模式,这一点是无法看出的,需要在递推的过程中得出。代码如下:
public class Solution { /** * @param s: A string * @param p: A string includes "?" and "*" * @return: is Match? */ public boolean isMatch(String s, String p) { // write your code here boolean[][] dp = new boolean[s.length() + 1][p.length() + 1]; for (int i = 0; i <= s.length(); i++) { for (int j = 0; j <= p.length(); j++) { // 空串可以匹配空模式,非空串无法匹配空模式 if (i == 0 && j == 0) { dp[i][j] = true; } else if (j == 0) { dp[i][j] = false; } else { // 如果模式串非空,考虑模式串最后一个字符是不是'*'; if (p.charAt(j - 1) != '*') { // 如果模式串最后一位不是'*',那么匹配当且仅当s非空,并且最后一个字符可以匹配,并且之前也可以匹配 if (i > 0 && (p.charAt(j - 1) == s.charAt(i - 1) || p.charAt(j - 1) == '?')) { dp[i][j] |= dp[i - 1][j - 1]; } } else { // 如果模式串最后一位是'*',那么要么将其视为空串,要么就需要s非空并且除去最后一位之后得到的子串与p匹配 dp[i][j] |= dp[i][j - 1]; if (i > 0) { dp[i][j] |= dp[i - 1][j]; } } } } } return dp[s.length()][p.length()]; } }时空复杂度 O ( l s l p ) O(l_sl_p) O(lslp)。