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).
Example
isMatch("aa","a") → false
isMatch("aa","aa") → true
isMatch("aaa","aa") → false
isMatch("aa", "*") → true
isMatch("aa", "a*") → true
isMatch("ab", "?*") → true
isMatch("aab", "c*a*b") → false
DP。 O(m*n), m为string长度,n为pattern长度
1.定义:dp[i][j]是s.substring(0, i)和p.substring(0, j)是否为匹配对,从头开始对比。
2.状态转移方程:
a)dp[i][j] = dp[i - 1][j - 1]; 在两个字符相等或p的字符为’?’时。(从左上来)
b)dp[i][j] = dp[i - 1][j] || dp[i][j - 1]; 在p的字符为’*’时。(从上来和从左来)
c)dp[i][j] = false; 其他情况,其实也就是两个字符不相同而且p的不是特殊字符时。
3.初始化:dp[0][0]=true, 第一行也就是声明空s是否匹配一段段pattern的时候,如果遇到p.c ==‘*’的情况,要取左边的值(为了保证比如aa能匹配上*)。第一列也就是声明空p是否匹配一段段的string,肯定都是false啊。
4.刷新方向,自上而下,从左到右。
5.具体解释:
2a)在字符串相等或者’?’被迫匹配到s的当前字符的时候,当前位置合格了,你得把这两个字符擦掉看前面的合格不合格。
2b)dp[i - 1][j]就是把s擦掉一个而p的*保留,也就是p发挥了万能符的通常作用代表了s里的其中一个字符,至于有没有进一步代表s里其他字符那是dp[i-1][j]帮你去判断的事。
dp[i][j - 1]就是把s保留而p的*擦掉一个,也就是p发挥了万能符的隐身作用,替代0个字符。
2c)普通字符当前位置都匹配不上那就不可能了,你整个字符串宏观看,最后一个是普通字符而且不一样的话,前面的*?再怎么巧妙也解决不了最后不同的问题啊。
细节:
1.数组大小是[s.length()+1][p.length()+1],留出上左的行列给初始化的。所以给数组赋值的下标和取substring的下标有一个offset,要小心。所以正式part循环是[1, length()],取char是substring(i - 1)。
参考视频:https://www.youtube.com/watch?v=3ZDZ-N0EPV0
我的实现
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[][] isMatch = new boolean[s.length() + 1][p.length() + 1]; isMatch[0][0] = true; for (int j = 1; j <= p.length(); j++) { // 注意数组的下标和读取string里的下标有一个offset! if (p.charAt(j - 1) == '*') { isMatch[0][j] = isMatch[0][j - 1]; } } for (int i = 1; i <= s.length(); i++) { for (int j = 1; j <= p.length(); j++) { if (s.charAt(i - 1) == p.charAt(j - 1) || p.charAt(j - 1) == '?') { isMatch[i][j] = isMatch[i - 1][j - 1]; } else if (p.charAt(j - 1) == '*') { isMatch[i][j] = isMatch[i - 1][j] || isMatch[i][j - 1]; } } } return isMatch[s.length()][p.length()]; } }