summary:
1.以pattern为主分类讨论,遍历 pattern 可能的情况, case by case,
2.递归出口: s 和 p正好遍历完成, 结果命中. corner case: s遍历完成,p还有尾巴,需要对p的尾巴进行删除操作
3.当前p idx 为 '*' 或 '.' 或 'character' 分别做特殊处理, 注意当前为 "*" 时需要进行回溯遍历从0到N个的情况
ps: 代码实现比较复杂,第一次做花了将近俩小时才AC,参考答案有非常clean的递归写法,但仍然保留这个原始思路吧,也算是对逻辑思维的一种锻炼 2020.5.5
package myapp.kit.leetcode.top100liked;
/**
*
* 10
* hard
* https://leetcode.com/problems/regular-expression-matching/
*
* 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 preceding 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
*
*
* @author Dingsheng Huang
* @version 1.0.0 2020/5/5 14:07
*/
public class RegularExpressionMatching {
boolean result = false;
public boolean isMatch(String s, String p) {
process(s, 0, p, 0);
return result;
}
// summary: 以pattern为主分类讨论,遍历 pattern 可能的情况, case by case,
// 递归出口: s 和 p正好遍历完成, 结果命中. corner case: s遍历完成,p还有尾巴,需要对p的尾巴进行删除操作
// 当前p idx 为 '*' 或 '.' 或 'character' 分别做特殊处理, 注意当前为 "*" 时需要进行回溯遍历从0到N个的情况
private void process(String s, int sIdx, String p, int pIdx) {
if (sIdx > s.length() - 1 && pIdx > p.length() - 1) {
result = true;
return;
}
if (pIdx > p.length() - 1 && sIdx <= s.length() - 1) {
return;
}
// corner case
if (pIdx <= p.length() - 1 && sIdx > s.length() - 1) {
result = delete(p, pIdx);
return;
}
char sCh = s.charAt(sIdx);
char pCh = p.charAt(pIdx);
if (pCh == '*') {
if (p.charAt(pIdx - 1) == s.charAt(sIdx)) {
int cn = 0;
int temp = sIdx;
while (temp < s.length() && s.charAt(temp) == sCh) {
cn++;
temp++;
}
for (int i = 0; i <= cn; i++) {
process(s, sIdx + i, p, pIdx + 1);
if (result == true) {
break;
}
}
} else if (p.charAt(pIdx - 1) == '.') {
int cn = s.length() - sIdx;
for (int i = 0; i <= cn; i++) {
process(s, sIdx + i, p, pIdx + 1);
if (result == true) {
break;
}
}
} else if (p.charAt(pIdx - 1) == '*') {
process(s, sIdx, p, pIdx + 1);
} else {
process(s, sIdx, p, pIdx + 1);
}
} else if (pCh == '.' || pCh == sCh) {
if ((pIdx + 1 <= p.length() - 1 && p.charAt(pIdx + 1) != '*') || pIdx == p.length() - 1) {
process(s, sIdx + 1, p, pIdx + 1);
} else {
process(s, sIdx, p, pIdx + 1);
}
} else {
if (pIdx + 1 > p.length() - 1 || p.charAt(pIdx + 1) != '*') {
return;
}
process(s, sIdx, p, pIdx + 1);
}
}
private boolean delete(String p, int pIdx) {
if (pIdx > p.length() - 1) {
return true;
}
if (p.charAt(pIdx) == '*') {
return delete(p, pIdx + 1);
} else {
if (pIdx + 1 > p.length() - 1 || p.charAt(pIdx + 1) != '*') {
return false;
}
return delete(p, pIdx + 1);
}
}
}