[leetcode] 10. Regular Expression Matching
原创
©著作权归作者所有:来自51CTO博客作者是念的原创作品,请联系作者获取转载授权,否则将追究法律责任
Description
Given an input string (s) and a pattern §, 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:
Output:
Explanation:
"a" does not match the entire string "aa".
Example 2:
Input:
Output:
Explanation:
'*' means zero or more of the precedeng element, 'a'. Therefore, by repeating 'a' once, it becomes "aa".
Example 3:
Input:
Output:
Explanation:
".*" means "zero or more (*) of any character (.)".
Example 4:
Input:
Output:
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:
分析
题目的意思是:
动态规划
dp[i][j]表示s[i-1]与p[j-1]是否匹配
如果 p[j-1] == s[i-1] || p[j-1] == ‘.’, 此时dp[i][j] = dp[i-1][j-1];
如果 p[j-1] == ‘*’
分两种情况:
1: 如果p[j-2] != s[i-1] && p[j-2] != ‘.’, 此时dp[i][j] = dp[i][j-2] //*前面字符匹配0次
2: 如果p[j-2] == s[i-1] || p[j-2] == ‘.’
此时dp[i][j] = dp[i][j-2] // *前面字符匹配0次
或者 dp[i][j] = dp[i][j-1] // *前面字符匹配1次
或者 dp[i][j] = dp[i-1][j] // *前面字符匹配多次
这题用递归的话,大致思路如下:
- 若p为空,s也为空,则返回true,否则返回false;
- 若p的长度为1,s的长度也为1,且相同或p为‘.’,则返回true,否则返回false;
- 若p的第二个字符不为*,此时s为空,则返回false,否则判断首字符是否匹配,且从各自的第二个字符开始调用递归函数;
- 若p的第二个字符为*,若s不空且字符匹配,调用递归函数s和去掉前两个字符的p,若匹配,则返回true,否则s去掉首字母;
- 返回调用递归函数匹配s和去掉前两个字符p的结果。
代码一 递归版本
class Solution {
public:
bool isMatch(string s, string p) {
if(p.empty()) return s.empty();
if(p.size()==1){
return s.size()==1&&(s[0]==p[0]||p[0]=='.');
}
if(p[1]!='*'){
if(s.empty()) return false;
return (s[0]==p[0]||p[0]=='.')&&isMatch(s.substr(1),p.substr(1));
}
while(!s.empty()&&(s[0]==p[0]||p[0]=='.')){
if(isMatch(s,p.substr(2))) return true;
s=s.substr(1);
}
return isMatch(s,p.substr(2));
}
};
代码二 动态规划版本
class Solution {
public:
bool isMatch(const char *s, const char *p) {
int m=strlen(s);
int n=strlen(p);
if(m==0&&n==0){
return true;
}
bool dp[m+1][n+1];
memset(dp,false,sizeof(dp));
dp[0][0]=true;
for(int i=1;i<=n;i++){
if(p[i-1]=='*'){
dp[0][i]=dp[0][i-2];
}
}
for(int i=1;i<=m;i++){
for(int j=1;j<=n;j++){
if(s[i-1]==p[j-1]||p[j-1]=='.'){
dp[i][j]=dp[i-1][j-1];
}else if(p[j-1]=='*'){
if(j!=1&&p[j-2]!='.'&&s[i-1]!=p[j-2]){
dp[i][j]=dp[i][j-2];
}else{
dp[i][j]=dp[i][j-1]||dp[i-1][j]||dp[i][j-2];
}
}
}
}
return dp[m][n];
}
};
参考文献
[编程题]regular-expression-matching[LeetCode] Regular Expression Matching 正则表达式匹配