10. Regular Expression Matching
by Botao Xiao
Given an input string (s) and a pattern (p), 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).
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 = "a*"
Output: true
Explanation: '*' means zero or more of the precedeng element, 'a'. Therefore, by repeating 'a' once, it becomes "aa".
Example 3:
Input:
s = "ab"
p = ".*"
Output: true
Explanation: ".*" means "zero or more (*) of any character (.)".
Example 4:
Input:
s = "aab"
p = "c*a*b"
Output: true
Explanation: c can be repeated 0 times, a can be repeated 1 time. Therefore it matches "aab".
Example 5:
Input:
s = "mississippi"
p = "mis*is*p*."
Output: false
Thinking:
- Method1:通过回溯法
class Solution {
public boolean isMatch(String s, String p) {
int sLen = s.length();
int pLen = p.length();
return myMatch(s, sLen - 1, p, pLen - 1);
}
public static boolean myMatch(String s, int i, String p, int j){
if(j == -1)
if(i == -1) return true;
else return false;
if(p.charAt(j) == '*'){
if( i > -1 && (p.charAt(j - 1) == s.charAt(i) || p.charAt(j - 1) == '.')){
if(myMatch(s, i - 1, p, j))
return true;
}
return myMatch(s, i, p, j - 2);
}
if(i > -1 && j > -1 && (p.charAt(j) == '.' || p.charAt(j) == s.charAt(i)))
return myMatch(s, i - 1, p, j - 1);
return false;
}
}
二刷
- 使用动态规划。
- 初始化
- dp[0][0] = true, 当两个字符串都是空串,一定是匹配的。
- 当s为空串,如果p当前字符是’’, 当前结果dp[0][j]和dp[0][j - 2]相同,因为可以代表出现0次。
- 动态规划
- 当p的当前字符是.或者和s当前字符相同,dp[i][j]=dp[i-1][j-1],前面一个字符匹配则当前字符匹配。
- 当p的当前字符是*
- 首先设置dp[i][j] = dp[i][j - 2], 说明前一个字符循环0次。
-
如果s的当前字符等于p的前一位字符, dp[i][j] = dp[i - 1][j],如果前一位匹配则当前也匹配。
- 初始化
class Solution {
public boolean isMatch(String s, String p) {
if(s == null || p == null) return false;
int len1 = s.length(), len2 = p.length();
boolean dp[][] = new boolean[len1 + 1][len2 + 1];
dp[0][0] = true;
for(int i = 1; i <= len2; i++)
if(p.charAt(i - 1) == '*') dp[0][i] = dp[0][i - 2];
for(int i = 1; i <= len1; i++){
char c1 = s.charAt(i - 1);
for(int j = 1; j <= len2; j++){
char c2 = p.charAt(j - 1);
if(match(c1, c2)){
dp[i][j] = dp[i - 1][j - 1];
}else{ // c2 == '*'
if(p.charAt(j - 1) == '*'){
dp[i][j] = dp[i][j - 2]; //skip current
if(j > 1 && match(c1, p.charAt(j - 2)))
dp[i][j] |= dp[i - 1][j];
}
}
}
}
return dp[len1][len2];
}
private boolean match(char c1, char c2){
return c2 == '.' || c1 == c2;
}
}
三刷
class Solution {
public boolean isMatch(String s, String p) {
if(s == null || p == null) return false;
int sLen = s.length(), pLen = p.length();
boolean[][] dp = new boolean[sLen + 1][pLen + 1];
dp[0][0] = true;
for(int i = 1; i <= pLen; i++)
if(p.charAt(i - 1) == '*') dp[0][i] = dp[0][i - 2];
for(int i = 1; i <= sLen; i++){
char c1 = s.charAt(i - 1);
for(int j = 1; j <= pLen; j ++){
char c2 = p.charAt(j - 1);
if(check(c1, c2)) dp[i][j] = dp[i - 1][j - 1];
else{
if(c2 == '*'){
dp[i][j] = dp[i][j - 2];
if(j > 1 && check(c1, p.charAt(j - 2)))
dp[i][j] |= dp[i - 1][j]; //唯一的难点就是为什么是j,是因为前一位也可能是通过匹配得到的。
}
}
}
}
return dp[sLen][pLen];
}
private boolean check(char c1, char c2){
return c1 == c2 || c2 == '.';
}
}
Subscribe via RSS