leetcode10+leetcode 44 正则匹配题型总结

正则匹配题型总结

这两道题目其实都是属于匹配类型的题目,都有一个‘*’表示可以任意匹配多个字符,而都有一个’.‘表示可以匹配单个字符。

比较好想的递归思路:
递归思路主要有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];
    }
};
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值