Problem
Given an input string s and a pattern p, implement regular expression matching with support for ‘.’ and ‘*’ where:
‘.’ Matches any single character.
‘*’ Matches zero or more of the preceding element.
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 = “cab”
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 = “misisp*.”
Output: false
Constraints:
1 <= s.length <= 20
1 <= p.length <= 30
s contains only lowercase English letters.
p contains only lowercase English letters, ‘.’, and ‘’.
It is guaranteed for each appearance of the character '’, there will be a previous valid character to match.
Analysis
Iterate two strings, match one by one.
为了方便,dp[i][j]均为闭区间
类似s.substr(0,i) p.substr(0,j)
- case 0:最容易想到的情况,没有通配符,直接往上一层比较
//判断条件:s[i-1]==p[j-1] || p[j-1]=='.'
dp[i][j]=dp[i-1][j-1]
不妨把判断条件写一个函数judge:
bool judge(char a,char b){return a==b||b=='.';}
-
case 1:p[j-1]==’*’
两种小情况:(1)不用这串通配符
dp[i][j]=dp[i][j-2]
(2)通配符循环使用
dp[i][j]=judge(str[i-1],pattern[j-2])&&dp[i-1][j]
Code
class Solution {
public:
bool match(string s, string p) {
int n=p.size();
int m=s.size();
vector<vector<int>> dp(m+1,vector<int>(n+1,0));
dp[0][0]=1;
for(int i=2;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(judge(s[i-1],p[j-1]))
dp[i][j]=dp[i-1][j-1];
else if(p[j-1]=='*')
dp[i][j]=dp[i][j-2]||judge(s[i-1],p[j-2])&&dp[i-1][j];
}
return dp[m][n];
}
private:
bool judge(char a,char b){return a==b||b=='.';}
};