正则表达式匹配Regular Expression Matching

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:
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

这道题中的* 表示之前那个字符可以有0个,1个或是多个,就是说,字符串a *b,可以表示b或是aaab,即a的个数任意,这道题分的情况的要复杂一些,需要用递归Recursion来解,大概思路如下:

  • 若p为空,若s也为空,返回true,反之返回false。

  • 若p的长度为1,若s长度也为1,且相同或是p为’.'则返回true,反之返回false。

  • 若p的第二个字符不为*,若此时s为空返回false,否则判断首字符是否匹配,且从各自的第二个字符开始调用递归函数匹配。

  • 若p的第二个字符为*,进行下列循环,条件是若s不为空且首字符匹配(包括p[0]为点),调用递归函数匹配s和去掉前两个字符的p(这样做的原因是假设此时的星号的作用是让前面的字符出现0次,验证是否匹配),若匹配返回true,否则s去掉首字母(因为此时首字母匹配了,我们可以去掉s的首字母,而p由于星号的作用,可以有任意个首字母,所以不需要去掉),继续进行循环。

  • 返回调用递归函数匹配s和去掉前两个字符的p的结果(这么做的原因是处理星号无法匹配的内容,比如s=“ab”, p=“a*b”,直接进入while循环后,我们发现"ab"和"b"不匹配,所以s变成"b",那么此时跳出循环后,就到最后的return来比较"b"和"b"了,返回true。再举个例子,比如s="", p=“a *”(a和 *之间没有空格),由于s为空,不会进入任何的if和while,只能到最后的return来比较了,返回true,正确)。

#include<iostream>
using namespace std;

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.size()==1)
	        if(s.size()==1 && (s[0]==p[0] || p[0]=='.'))
	        	return true;
	        else
	        	return false;
        //但上面不能这么写,下面是错误写法。
        if(p.size()==1 && s.size()==1 && (s[0]==p[0] || p[0]=='.'))
        	return true;
        else
        	return false;
        //仔细体会两种写法的区别,别搞错了。错误写法的错误之处在于当p.size()不为1时就会返回false,这样显然有问题
         */
        if(p[1] != '*'){
        	if(s.empty()) return false;
        	return ((s[0]==p[0] || p[0]=='.') && isMatch(s.substr(1),p.substr(1)));  
        	//当s和p的长度大于1且p的第二个不是*时,要一个一个地比较s和p的元素,并每次都去掉开头第一个位置的元素
        }
        while(!s.empty() && (s[0]==p[0] || p[0]=='.')){
        	if(isMatch(s,p.substr(2)))  return true;  //这样做的原因是假设此时的星号的作用是让前面的字符出现0次,验证是否匹配
        	s=s.substr(1);  //因为此时首字母匹配了,我们可以去掉s的首字母,而p由于星号的作用,可以有任意个首字母,所以不需要去掉
        }
        return isMatch(s,p.substr(2));
        //上面这个return,也就是最后一个return作用是:
        //这么做的原因是处理星号无法匹配的内容,比如s="ab", p="a*b",直接进入while循环后,我们发现"ab"和"b"不匹配,所以s变成"b",那么此时跳出循环后,就到最后的return来比较"b"和"b"了,返回true。
        //再举个例子,比如s="", p="a*",由于s为空,不会进入任何的if和while,只能到最后的return来比较了,返回true,正确
    }
};

int main(){
	Solution S;
	cout << S.isMatch("ab","a*b");
	return 0;
}

参考网址:
http://www.cnblogs.com/grandyang/p/4461713.html
https://leetcode.com/problems/regular-expression-matching/

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值