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 lettersa-z
.p
could be empty and contains only lowercase lettersa-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
题目链接:https://leetcode.com/problems/regular-expression-matching/
题目分析:考虑模式串p的长度,分为以下四种情况
1. len(p) == 0,判断是否len(s) == 0
2. len(p) == 1,判断是否len(s) == 1且 (p[0]=s[0] 或 p[0]='.')
3. len(p) > 1 && p[1] != '*',判断当前的p和s的首字母是否匹配
4. len(p) > 1 && p[1] == '*',由于*可消掉前面的字符,此处需要分两种情况讨论 a)消掉前面的字符 b)匹配前面的字符一次
最后需要消掉通配符'*'
暴力DFS,64ms,时间击败21.6%
class Solution {
public static boolean isFirstPosMatch(String s, String p) {
return !s.isEmpty() && (s.charAt(0) == p.charAt(0) || p.charAt(0) == '.');
}
public boolean isMatch(String s, String p) {
if (p.isEmpty()) {
return s.isEmpty();
}
if (p.length() == 1) {
return s.length() == 1 && isFirstPosMatch(s, p);
}
if (p.charAt(1) != '*') {
return isFirstPosMatch(s, p) && isMatch(s.substring(1), p.substring(1));
}
while (isFirstPosMatch(s, p)) {
if (isMatch(s, p.substring(2))) {
return true;
}
s = s.substring(1);
}
return isMatch(s, p.substring(2));
}
}
显然substring影响了运行效率,改写用下标记录位置,11ms,时间击败92.6%
class Solution {
public static boolean isFirstPosMatch(String s, int spos, String p, int ppos) {
return spos < s.length() && (s.charAt(spos) == p.charAt(ppos) || p.charAt(ppos) == '.');
}
public boolean isMatch(String s, String p) {
return isMatchHelper(s, 0, p, 0);
}
public boolean isMatchHelper(String s, int spos, String p, int ppos) {
if (ppos == p.length()) {
return spos == s.length();
}
if (ppos == p.length() - 1) {
return spos == s.length() - 1 && isFirstPosMatch(s, spos, p, ppos);
}
if (p.charAt(ppos + 1) != '*') {
return isFirstPosMatch(s, spos, p, ppos) &&
isMatchHelper(s, spos + 1, p, ppos + 1);
}
while (isFirstPosMatch(s, spos, p, ppos)) {
if (isMatchHelper(s, spos, p, ppos + 2)) {
return true;
}
spos++;
}
return isMatchHelper(s, spos, p, ppos + 2);
}
}
不难发现求解过程中可能存在重复子问题,对答案记忆化一下,1ms,时间击败100%
class Solution {
public static boolean isFirstPosMatch(String s, int spos, String p, int ppos) {
return spos < s.length() && (s.charAt(spos) == p.charAt(ppos) || p.charAt(ppos) == '.');
}
public boolean isMatch(String s, String p) {
int[][] match = new int[s.length() + 1][p.length() + 1];
return isMatchHelper(s, 0, p, 0, match);
}
public boolean isMatchHelper(String s, int spos, String p, int ppos, int[][] match) {
if (match[spos][ppos] != 0) {
return match[spos][ppos] == 1 ? true : false;
}
if (ppos == p.length()) {
match[spos][ppos] = (spos == s.length()) ? 1 : -1;
return match[spos][ppos] == 1;
}
if (ppos == p.length() - 1) {
match[spos][ppos] = (spos == s.length() - 1 && isFirstPosMatch(s, spos, p, ppos)) ? 1 : -1;
return match[spos][ppos] == 1;
}
if (p.charAt(ppos + 1) != '*') {
match[spos][ppos] = (isFirstPosMatch(s, spos, p, ppos) &&
isMatchHelper(s, spos + 1, p, ppos + 1, match)) ? 1 : -1;
return match[spos][ppos] == 1;
}
while (isFirstPosMatch(s, spos, p, ppos)) {
match[spos][ppos] = (isMatchHelper(s, spos, p, ppos + 2, match)) ? 1 : -1;
if (match[spos][ppos] == 1) {
return true;
}
spos++;
}
match[spos][ppos] = (isMatchHelper(s, spos, p, ppos + 2, match)) ? 1 : -1;
return match[spos][ppos] == 1;
}
}