题目
给你一个字符串
s
和一个字符规律p
,请你来实现一个支持'.'
和'*'
的正则表达式匹配。
'.'
匹配任意单个字符'*'
匹配零个或多个前面的那一个元素所谓匹配,是要涵盖 整个 字符串
s
的,而不是部分字符串。
思路1
递归回溯,把所有可能的情况全部试一遍:
- 不停剪去s和p相同的首部,直到某一个或两个都被剪空
- s.charAt(0) == p.charAt(0) || p.charAt(0) == '.'
‘*’前的元素可以出现0次或者多次,当p中第i个元素的下一个元素为‘*’时:
- ① p的第i个元素在s中出现0次
- 保持s不变,将p剪2个元素,继续调用isMatch
- ② p的第i个元素在s中出现多次
- 比较i元素与s的首元素,如果相同,剪去s的首元素,保持p不变,继续调用isMatch
代码1
class Solution {
public boolean isMatch(String s, String p) {
// p为空时,判断s是否为空
if (p == null || p.length() == 0)
return s == null || s.length() == 0;
// 查看首元素是否一致
boolean str = s.length() != 0 && (s.charAt(0) == p.charAt(0) || p.charAt(0) == '.');
// 如果下一个字符是‘*’
if (p.length() > 1 && p.charAt(1) == '*')
return isMatch(s, p.substring(2)) || (str && isMatch(s.substring(1), p));
// 如果下一个字符不是‘*’
else
return str && isMatch(s.substring(1), p.substring(1));
}
}
思路2
动态规划,解决字符串匹配问题:
- ① 初始化dp[i][j]=false
- boolean dp[][] = new boolean[s.length() + 1][p.length() + 1];
- ② 当s为null时,看p的情况
- ③ 如果s[i-1]==p[j-1]||p[j-1]=='.',则dp[i][j]=dp[i-1][j-1]
- ④ 如果p[j-1]=='*'有三种情况,第一种是p[j-1]=='.'||s[i]==p[j-1]情况匹配1个元素i-1,第二种是p[j-1]=='.'||s[i]==p[j-1]情况但是不匹配直接跳过j-2,第三种情况是p[j-1]!='.'&&s[i]!=p[j-1]不匹配跳过j-2
代码2
class Solution {
public boolean isMatch(String s, String p) {
boolean dp[][] = new boolean[s.length() + 1][p.length() + 1];
dp[0][0] = true;
for (int i = 2; i < p.length() + 1; i++) {
if (p.charAt(i - 1) == '*')
dp[0][i] = dp[0][i - 2];
}
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) == '.')
dp[i][j] = dp[i - 1][j - 1];
else if (p.charAt(j - 1) == '*') {
if (p.charAt(j - 2) != '.' && p.charAt(j - 2) != s.charAt(i - 1))
dp[i][j] = dp[i][j - 2];
else
dp[i][j] = (dp[i][j - 2] || dp[i][j - 1] || dp[i - 1][j]);
}
}
}
return dp[s.length()][p.length()];
}
}