正则匹配题型总结
这两道题目其实都是属于匹配类型的题目,都有一个‘*’表示可以任意匹配多个字符,而都有一个’.‘表示可以匹配单个字符。
比较好想的递归思路:
递归思路主要有2种,一种是从前向后匹配,一种是从后往前匹配。多数时候两种都可以,我这里主要用的是从前向后匹配,所以我定义的dp[i][j]为s的第i个字符之后和p的第j个字符之后可以互相匹配上的概率。
这样的话逻辑就比较清晰了,初始化dp[i][j]都为-1,表示都没有访问过,没有记录。然后在每次递归的时候,先判断是否到达终点,先判断p到达终点没有,再判断s到达终点没有,然后再看是否有访问过,进行记忆化搜索。
接下来看是否有’*'
没有的话就有first匹配,匹配完了就进行后续的匹配了,return的时候要记录下dp[i][j];
如果有的话,那么分两种情况,一种是’ * ’ 完全不起作用,则p直接后退,一种是p起作用了,那么p此时是不后退的,但是s会后退,这样进行下一个递归的时候,仍然有’ * '。
这里这个p仅仅后退一个是非常重要的!因为我们是不断的尝试匹配,因此每次只能匹配一个,我第一次写的时候连续匹配好几个,导致了出错,这里要特别注意!
leetcode 10
dp[i][j]表示从s[i],p[j]开始往后的是否能匹配上,包括s[i],p[j]
class Solution {
public:
vector<vector<int>>dp;
bool DP(string& s, string& p, int i, int j, vector<vector<int>>& dp) {
int lens = s.size();
int lenp = p.size();
//如果p已经到结尾了,此时p往后为空,如果s也为空则匹配,否则不匹配
if (j == lenp) {
bool ans = (i == lens);
dp[i][j] = ans;
return dp[i][j];
}
if (dp[i][j] != -1)return dp[i][j];
//第一匹配
bool first = false;
if (i<lens) {
if (s[i] == p[j] || p[j] == '.') {
first = true;
}
}
if (j<(lenp - 1) && p[j + 1] == '*') {
//bool situation1 = DP(s, p, i, j + 2, dp);
//bool situation2 = first&&DP(s, p, i + 1, j, dp);
//dp[i][j] = situation1 || situation2;
//return dp[i][j];
return dp[i][j] = (DP(s, p, i, j + 2,dp) || first == true && DP(s, p, i + 1, j,dp));
}
else {
//bool situation3 = DP(s, p, i + 1, j + 1, dp);
//dp[i][j] = first&&situation3;
//return dp[i][j];
return dp[i][j] = (first && DP(s, p, i + 1, j + 1,dp));
}
}
bool isMatch(string s, string p) {
int n = s.size();
int m = p.size();
//vector<vector<int>>dp(n+1, vector<int>(m+1, -1));
dp.assign(s.size() + 1, vector<int>(p.size() + 1, -1));
bool ans = DP(s, p, 0, 0, dp);
return dp[0][0];
}
};
leetcode 44
dp[i][j]表示从s[i],p[j]开始往后的是否能匹配上,包括s[i],p[j]
class Solution {
public:
bool DP(string& s,string& p,int i,int j,vector<vector<int>>& dp){
//定义dp[i][j]为s的第i个字符往后和p第j个字符往后是否匹配
int lens=s.size();
int lenp=p.size();
if(j==lenp){
return dp[i][j]=i==lens;
}
if(i==lens){
for(int k=j;k<lenp;k++){
if(p[k]!='*'){
return dp[i][j]=false;
}
}
return dp[i][j]=true;
}
if(dp[i][j]!=-1)return dp[i][j];
if(p[j]!='*'){
bool first=(p[j]==s[i]||p[j]=='?') ;
return dp[i][j]=first&&DP(s,p,i+1,j+1,dp);
}
return dp[i][j]=DP(s,p,i+1,j,dp)||DP(s,p,i,j+1,dp);
}
bool isMatch(string s, string p) {
int m=s.size();
int n=p.size();
vector<vector<int>> dp(m+1,vector<int>(n+1,-1));
DP(s,p,0,0,dp);
return dp[0][0];
}
};