10. Regular Expression Matching & Wildcard Matching
Regular Expression Matching
Implement regular expression matching with support for '.'
and '*'
.
'.' Matches any single character. '*' Matches zero or more of the preceding element. The matching should cover the entire input string (not partial). The function prototype should be: bool isMatch(const char *s, const char *p)
isMatch("aa","a") → false isMatch("aa","aa") → true isMatch("aaa","aa") → false isMatch("aa", "a*") → true isMatch("aa", ".*") → true isMatch("ab", ".*") → true isMatch("aab", "c*a*b") → true
int m = p.length();
int n = s.length();
boolean[][] match = new boolean[m + 1][n + 1]; (p是横轴,s是纵轴)
match[i][j]表明对于p的前i - 1个字符,是否匹配s的前j - 1个字符。
这里分几种情况:
如果p.chartAt(i - 1) 是“.” 或者p.charAt(i - 1) == s.charAt(j - 1), 那么我们有:
match[i][j] = match[i - 1][j - 1];
如果p.chartAt(i - 1) 不是“.” 并且 p.charAt(i - 1) != s.charAt(j - 1), 那么我们有:
match[i][j] = false;
好了,关键点来了,如果p.chartAt(i - 1) == ‘*’,那么怎么办呢?
首先,如果p.charAt(i - 2) == '.' || p.charAt(i - 2) == s.charAt(j - 1)
那么我们是不是可以取match[i - 1][j - 1] (因为p.charAt(i - 1) == s.charAt(j - 1)如果上面条件成立), 或者 match[i - 2][j] ("x*" 直接变成 “”), 或者match[i][j - 1] ("x*" 变成 “x*x”) || match[i - 1][j] ("x*"变成 “x”);
所以,我们有: match[i][j] = match[i - 1][j - 1] || match[i - 2][j] || match[i][j - 1] || match[i - 1][j];
如果p.charAt(i - 2) != s.charAt(j - 1), 我们就只有一种方法:
match[i][j] = match[i - 2][j];
1 public class Solution { 2 public boolean isMatch(String s, String p) { 3 if (s == null || p == null) return false; 4 5 while (p.length() >= 1 && p.charAt(0) == '*') { 6 p = p.substring(1); 7 } 8 int row = p.length(), col = s.length(); 9 boolean[][] match = new boolean[row + 1][col + 1]; 10 match[0][0] = true; 11 for (int i = 1; i <= row; i++) { 12 if (p.charAt(i - 1) == '*') { 13 match[i][0] = match[i - 2][0]; 14 } 15 } 16 17 for (int i = 1; i <= row; i++) { 18 for (int j = 1; j <= col; j++) { 19 if (p.charAt(i - 1) == s.charAt(j - 1) || p.charAt(i - 1) == '.') { 20 match[i][j] = match[i - 1][j - 1]; 21 } else if (p.charAt(i - 1) == '*') { 22 if (p.charAt(i - 2) == '.' || p.charAt(i - 2) == s.charAt(j - 1)) { 23 match[i][j] = match[i - 1][j - 1] || match[i - 2][j] || match[i][j - 1] || match[i - 1][j]; 24 } else { 25 match[i][j] = match[i - 2][j]; 26 } 27 } 28 } 29 } 30 return match[row][col]; 31 } 32 }
Wildcard Matching
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).
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问题,横轴是S, 纵轴是P(含有?和*),那么我们可以得到:
if (p.charAt(i - 1) == s.charAt(j - 1) || p.charAt(i - 1) == '?') {
match[i][j] = match[i - 1][j - 1];
} else if (p.charAt(i - 1) == '*') {
match[i][j] = match[i - 1][j - 1] || match[i - 1][j] || match[i][j - 1];
// match[i][j - 1] 指的是用* 替换S中1个j或多个j之前的character,当然那些character可以是连续的。
}
1 public class Solution { 2 public boolean isMatch(String s, String p) { 3 if (s == null || p == null) return false; 4 boolean[][] match = new boolean[p.length() + 1][s.length() + 1]; 5 match[0][0] = true; 6 for (int i = 1; i < match.length; i++) { 7 if (p.charAt(i - 1) == '*') { 8 match[i][0] = match[i - 1][0]; 9 } 10 } 11 12 for (int i = 1; i < match.length; i++) { 13 for (int j = 1; j < match[0].length; j++) { 14 if (p.charAt(i - 1) == s.charAt(j - 1) || p.charAt(i - 1) == '?') { 15 match[i][j] = match[i - 1][j - 1]; 16 } else if (p.charAt(i - 1) == '*') { 17 match[i][j] = match[i - 1][j - 1] || match[i - 1][j] || match[i][j - 1]; 18 } 19 } 20 } 21 return match[p.length()][s.length()]; 22 } 23 }