正则表达式匹配
题目:
正则表达式匹配 (leetcode 10/ 剑指offer 19):
请实现一个函数用来匹配包含’. ‘和’‘的正则表达式。模式中的字符’.‘表示任意一个字符,而’'表示它前面的字符可以出现任意次(含0次)。在本题中,匹配是指字符串的所有字符匹配整个模式。例如,字符串"aaa"与模式"a.a"和"abaca"匹配,但与"aa.a"和"ab*a"均不匹配。
解题思路:
1. 非正规解题思路:使用java/python
自带的正则表达式库:
import re
class Solution:
def isMatch(self, s: str, p: str) -> bool:
pattern = re.compile(p + '$')
matcher = pattern.match(s)
return matcher is not None
或者一行代码解决问题:
import re
class Solution:
def isMatch(self, s: str, p: str) -> bool:
return re.match(s, p + '$')
使用java
自带的正则表达式库:
import java.util.regex.*;
class Solution {
public boolean isMatch(String s, String p) {
Pattern pattern = Pattern.compile(p + "$");
Matcher match = pattern.matcher(s);
return match.matches();
}
}
import java.util.regex.*;
class Solution {
public boolean isMatch(String s, String p) {
return Pattern.matches(p + '$', s);
}
}
2. 动态规划
用dp[i][j]
表示字符串
s
s
s的前
i
i
i个字符与模式
p
p
p的前
j
j
j个字符是否匹配,则:
- 当
s[i] == p[j] or p[j] == '.'
时,dp[i][j] = dp[i - 1][j - 1]
; - 当
p[j] == '*'
且s[i] != p[j-1] && p[j - 1] != '.'
时,说明*
以及其前面的一个字符并没有匹配任何s
中的字符,因此dp[i][j] - dp[i][j - 2]
; - 当
p[j] == '*'
且s[i] == p[j-1] || p[j - 1] == '.'
时,dp[i][j] = dp[i - 1][j] | dp[i][j - 2]
。这是因为:- 如果
*
及之前的字符匹配了s
中的一个或多个字符的话,显然dp[i][j] = dp[i - 1][j]
; - 即使当
s[i] == p[j - 1] || p[j - 1] == '.'
时,*
及其前面的字符仍然有匹配0个字符的情况从在,例如s = "aa", p = "aa*a"
,显然 p p p中的a*
没有匹配任何字符,所以有dp[i][j] = dp[i][j - 2]
;
综合以上两种情况,dp[i][j] = dp[i-1][j] | dp[i][j-2]
。
- 如果
- 当
s[i] != p[j] && p[j] != '.'
时,dp[i][j] = false
;
建立好状态转移方程之后,可以写出如下的代码:
public boolean isMatch(String s, String p) {
boolean dp[][] = new boolean[s.length() + 1][p.length() + 1];
dp[0][0] = true;
for(int i = 1; i < dp.length; i++){
dp[i][0] = false;
}
for (int i = 1; i < dp[0].length; i++) {
if (p.charAt(i - 1) == '*') dp[0][i] = dp[0][i - 2];
else dp[0][i] = false;
}
for (int i = 1; i <= s.length(); i++) {
for (int j = 1; j <= p.length(); j++) {
int si = i - 1, sj = j - 1;
if(s.charAt(si) == p.charAt(sj) || p.charAt(sj) == '.') dp[i][j] = dp[i - 1][j - 1];
else if (p.charAt(sj) == '*') {
if (s.charAt(si) != p.charAt(sj - 1) && p.charAt(sj - 1) != '.') dp[i][j] = dp[i][j - 2];
else {
dp[i][j] = false;
dp[i][j] |= dp[i][j - 2];
dp[i][j] |= dp[i - 1][j];
dp[i][j] |= dp[i - 1][j - 2];
}
}
else dp[i][j] = false;
}
}
return dp[s.length()][p.length()];
}