LeetCode(10)RegularExpresssionMatching

原创 2013年12月06日 07:19:34

我觉这道题目得挺难的,想了很久也没想清楚%>_<%于是看了解题报告

题目解释

'.' Matches any single character.
'*' Matches zero or more of the preceding element.
The matching should cover the entire input string (not partial).
The function prototype should be:
bool isMatch(const char *s, const char *p)
Some examples:
isMatch("aa","a") → false
isMatch("aa","aa") → true
isMatch("aaa","aa") → false
isMatch("aa", "a*") → true
isMatch("aa", ".*") → true
isMatch("ab", ".*") → true
isMatch("aab", "c*a*b") → true

给定的例子中,有一个比较难懂,是这样的。
isMatch("ab", ".*") → true
这个式子的判定结果是true。理由是.*理解为重复任意字符任意次.......而a是任意字符,b也是任意字符。所以ture


基本思路:
比较困难的问题在这里。看下面两个例子的比较:
例1: isMatch("aaaaab","a*b"),
为了表达方便记录为    isMatch("a1a2a3a4a5b1","a6*b2"),
显然a6应该匹配a1a2a3a4a5,然后b2匹配b1。

例2: isMatch("aaaaab","a*ab"),
为了表达方便记录为    isMatch("a1a2a3a4a5b1","a6*a7b2"),
显然a6应该匹配a1a2a3a4,然后a7匹配a5,然后b2匹配b1。
于是发现,当正则表达式中有*的时候,比较讨厌,你不知道到底要在s中匹配多长。
这个问题的结构说明这个问题天生适合用递归来解决。就像leetcode的解答报告中说的If you are stuck, recursion is your friend.
这个问题的结构还说明*很特殊所以需要特殊对待,于是基本思路是
把p分隔为若干个小单位,要么是一个字符构成的小单位,要么是一个字符和后面一个'*'构成的小单位。
逐一检查这样的小单位是否能够和s匹配。这其中,到底这样的小单位匹配多长的s是需要我们逐一检查的,也就是需要我们暴力一下的。

抄袭代码:

//
//  Solution.h
//  LeetCodeOJ_010_RegMatching
//
//  Created by feliciafay on 12/4/13.
//  Copyright (c) 2013 feliciafay. All rights reserved.
//

#ifndef LeetCodeOJ_010_RegMatching_Solution_h
#define LeetCodeOJ_010_RegMatching_Solution_h
#include <iostream>
#include <string>
#include <assert.h>
// Input:	"bbbba", ".*a*a"
class Solution {
public:
    bool isMatch(const char *s, const char *p) {
        assert(s && p);
        if (*p == '\0') return *s == '\0';
        
        // next char is not '*': must match current character
        if (*(p+1) != '*') {
            assert(*p != '*');
            return ((*p == *s) || (*p == '.' && *s != '\0')) && isMatch(s+1, p+1);
        }
        // next char is '*'
        while ((*p == *s) || (*p == '.' && *s != '\0')) {
            if (isMatch(s, p+2))
                return true;
            s++;
        }
        //继续匹配剩下的部分
        return isMatch(s, p+2);
        }
};
#endif

小结
(1)欣赏一下这句的简洁和巧妙 
return ((*p == *s) || (*p == '.' && *s != '\0')) && isMatch(s+1, p+1);
(2)
注意这里是
    if (isMatch(s, p+2)) return true;
而不是
    return  (isMatch(s, p+2));
因为逻辑是,在若干次暴力搜索中,只要又一次匹配就返回true,不管之前失败了几次。
(3)
之前个人错误地认为逻辑其实应该是
//错误写法
s++;
if (isMatch(s, p+2)) return true;
但是实际正确写法却是

if (isMatch(s, p+2)) return true;
s++;
为什么呢?

看这样一个例子就能理解了。 isMatch(“a”, "a*a"),这里"a"和"a*a"显然应该是匹配的。为了方便,表达为
原串: a1
正则: a2*a3
如果按照错误写法,那么a1匹配a2之后,将检查a3和'\0'发现不匹配于是返回结果为不匹配。
可是实际上,a2*表达的意思是把a2重复0次或者多次,错误的写法没有考虑到把a2重复0次的情况。
按照正确的写法,就可以考虑到a2重复0次的情况,从而判断a1是否匹配a3,从将最终结果返回为匹配。
所以正确的写法是

if (isMatch(s, p+2)) return true;
s++;
(4) LeetCode对思路讲解的的原话

We need some kind of backtracking mechanism such that when a matching fails, we return to the last successful matching state and attempt to match more characters in s with ‘*’. This approach leads naturally to recursion.

If the next character of p is NOT ‘*’, then it must match the current character of s. Continue pattern matching with the next character of both s and p.
If the next character of p is ‘*’, then we do a brute force exhaustive matching of 0, 1, or more repeats of current character of p… Until we could not match any more characters.

相关文章推荐

leetcode 10: Regular Expression Matching

Regular Expression Matching Total Accepted: 39732 Total Submissions: 192279 Implement re...
  • xudli
  • xudli
  • 2015年05月01日 02:22
  • 2185

LeetCode 10. Regular Expression Matching(正则表达式匹配)

原题网址:https://leetcode.com/problems/regular-expression-matching/ Implement regular expression match...
  • jmspan
  • jmspan
  • 2016年05月19日 05:10
  • 878

LeetCode10. Regular Expression Matching有点难

Implement regular expression matching with support for '.' and '*'. '.' Matches any single characte...

LeetCode总结

最近完成了www.leetcode.com的online judge中151道算法题目。除各个题目有特殊巧妙的解法以外,大部分题目都是经典的算法或者数据结构,因此做了如下小结...
  • lanxu_yy
  • lanxu_yy
  • 2014年01月04日 20:19
  • 118493

leetcode刷题,总结,记录,备忘 19

leetcode19Remove Nth Node From End of List Given a linked list, remove the nth node from the en...

爬楼梯(leetcode-70)

需要爬一个n阶楼梯来到达楼梯顶部,每次可以爬1阶也可以爬2阶。求共有多少种爬法? 递归:到达n的“前一步”走法可以是:从n-1处爬1阶楼梯,或者从n-2处爬2阶楼梯。那么递归表达式即写成return ...

C/C++的static关键字

static主要有三个作用: (1)局部静态变量 (2)外部静态变量/函数 (3)静态数据成员/成员函数  前两种C和C++都有,第三种仅在C++中有,下面分别作以下介绍: 一、局部静态...

二叉树两个结点的最低共同父结点

入二叉树中的两个结点,输出这两个结点在数中最低的共同父结点。 分析:求数中两个结点的最低共同结点是面试中经常出现的一个问题。这个问题至 少有两个变种。 第一变种是二叉树是一种特殊的二叉树:查找二叉树。...

LeetCode 10_Regular Expression Matching

又两天没更新了,这两天倒不是偷懒了,而是遇到了一个难题,这两天一直在思考这个问题,今天做一个了结吧。 这是leetcode的第10题,难度为hard,是leetcode里难度等级最大的题目了,由于上一...
  • cyfcsd
  • cyfcsd
  • 2015年09月05日 21:15
  • 214

LeetCode 10 Regular Expression Matching (C,C++,Java,Python)

Problem: Implement regular expression matching with support for '.' and '*'. '.' Matches any singl...
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:LeetCode(10)RegularExpresssionMatching
举报原因:
原因补充:

(最多只允许输入30个字)