Leetcode10:Regular Expression Matching

题目描述

Given an input string (s) and a pattern (p), 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:
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 precedeng 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 = "c*a*b"
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 = "mis*is*p*."
Output: false

分析

这道题还是比较有难度的,如果情况考虑不全的话,是很难通过的。这道题最简单的思路就是递归,只是这个递归的情况很多,有多种特殊情况需要单独考虑。另外在思考前需要明确一点,*号之前必须要有一个有效元素。

首先就考虑特殊情况,当p为空时,如果s为空返回true;如果s不为空返回false。当p的长度为1时,如果s的长度不为1返回false;如果s的长度为1,并且s和p的字母匹配,或者p为‘.’,则返回true;否则返回false。

如果p的第二个元素不为*,如果s为空返回false;如果s不为空且s和p的第一个元素匹配,则递归匹配s和p的后续元素;否则返回false。

接着就需要考虑p的第二个元素为*的情况了,这个情况是比较复杂的,因为不知道一个元素会重复多少次,所以需要使用循环来判断。在进入循环前,需要判断s是否为空,如果为空直接退出循环。因为如果p的第一个元素为‘.’,那么就有可能s一直在缩小,而p在每次循环都是不变的。这是因为s和p本身是不匹配的,所以最终s会为空,但是出现不匹配的情况,因此循环条件需要加上s不为空的情况。另外还要判断s和p的第一个元素是否匹配,如果匹配就进入循环。

循环里面首先递归匹配s和p的第三个元素开始是否匹配,这个情况就相当于*不再重复其前面的一个元素。如果匹配直接返回true;否则s从后面一个元素开始,再次进入循环,相对于p之前的元素重复次数加1。

退出循环后还需要进行一次递归匹配,匹配现在的s和p的第三个元素开始是否匹配,这是因为循环中有些情况匹配不到,所以需要最后来进行处理。比如s=“ab”,p=“a*b”。退出循环后s=“b”,而p没有变。如果p不从第三个元素开始匹配,就不会匹配到。

这道题的情况比较多,需要仔细考虑,一不小心就会考虑不全或者考虑错误。

AC代码如下:

class Solution {
public:
    bool isMatch(string s, string p) {
        if(p.empty())//为空
        {
        	return s.empty();
		}
        if(p.length() == 1)//长度为1
		{
			if(s.length() == 1)
			{
				if(s[0] == p[0] || p[0] == '.')
				{
					return true;
				}
				return false;
			}
			return false;//s长度不为1则匹配不成功
        }
        if(p[1] != '*')//p的第二个元素不为*
		{
            if(s.empty())//s不能为空
            {
            	return false;
			}
			if(s[0] == p[0] || p[0] == '.')//s和p的第一个元素匹配
			{
				return isMatch(s.substr(1), p.substr(1));//递归匹配
			}
            return false;//s和p的第一个元素不匹配
        }
        while(!s.empty() && (s[0] == p[0] || p[0] == '.'))
		{
            if(isMatch(s, p.substr(2)))//递归匹配,跳过*
			{
				return true;
			}
			else
			{
				s = s.substr(1);//相当于*前面的元素重复出现
			}
        }
        return isMatch(s, p.substr(2));//匹配剩下的情况,跳过*,不过此时s已经变化
    }
};
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值