码迷,mamicode.com
首页 > 其他好文 > 详细

leetcode problem 10 Regular Expression Matching

时间:2015-04-17 13:37:58      阅读:120      评论:0      收藏:0      [点我收藏+]

标签:

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).

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



有两种方法, 一种是递归直接匹配,比较好理解,代码简洁。
      另一种是DP,时间复杂度小 ,为O(m*n) 其中m是匹配串长度,n是模式串长度。

先说第一种:
    设S为匹配串,P为模式串,令i指向匹配串Si,令j指向模式串Pj,判断P[j+1]是否为* 如果不是*,判断S[i] == P[j] ? 如果等于,则递归处理S[i+1] P[j+1],不等于则返回false。如果P[j+1]是*,则需要综合考虑两种情况,一个是*表示前一个字符重复0次,
  另一种情况是前一个字符重复 >=1次的情况,并对这两种情况取"或"。 看代码很容易理解的

Runtime: 40 ms
#define ISMATCH(a, b) (a != ‘\0‘ && (a == b || b == ‘.‘))

class Solution {
public:
    bool isMatch(const char *s, const char *p, int i = 0, int j = 0) {
        if (p[j] == \0) 
            return s[i] == \0;
        if (p[j+1] != *) 
            return ISMATCH(s[i], p[j]) && isMatch(s, p, i+1, j+1);
        if (p[j+1] == *) {
            return     //0 times
                isMatch(s, p, i, j+2) ||
                    // more times 
                (ISMATCH(s[i], p[j]) && isMatch(s, p, i+1, j));
        }
        return false;
    }
};

 

第二种方法用的是动态规划,非常巧妙。时间复杂度比较低为O(m*n)
  令dp[i][j]表示匹配串S[1..i]是否与模式串P[1..j]匹配。 dp[i][j] = true表示匹配,dp[i][j] = false表示不匹配,状态转移方程可以写成这样:

           dp[i][j-2]                 if P[j] == ‘*‘ 考虑*表示重复前一字符为0次的情况
    dp[i][j] = dp[i][j-1]                  if P[j] == ‘*‘ 考虑*表示重复前一字符为1次的情况(注意这里不用重复字符大于一次的情况,因为其实将来的状态矩阵中已经保存了的, 如dp[i][j]表示重复一次的情况且P[j] = ‘*‘, 那么dp[i+1][j]表示重复2次的情况,
                                                            dp[i+2][j]表示重复3次的情况,一次类推.)
           dp[i-1][j-1] && S[i] == S[j]       if P[j] != ‘*‘


其实只要理解了dp[i][j]表示什么意思,就很好解释了。
代码如下(做了一些优化,本来状态矩阵需要DP[m][n]的空间代价的,但是由于状态转移方程中在获得dp[i][j]时只用到了dp[i][j-2],所以可以只用dp[1..n]来维护状态)
Runtime: 10 ms
#define ISMATCH(a, b) (a == b ||(a != ‘\0‘ && b == ‘.‘))


class Solution {
public:
    bool isMatch(const char *s, const char *p) {
        int lenS = strlen(s);
        int lenP = strlen(p);

        vector<bool> dp(lenS+1, false);
        dp[0] = true;

        for (int j = 0; j < lenP; ++j) {
            if (j+1 < lenP && p[j+1] == *)
                continue;
            if (p[j] == *) {
                for (int i = 1; i <= lenS; ++i) {
                    dp[i] = dp[i] || (dp[i-1] && ISMATCH(s[i-1], p[j-1]));
                }
            }
            else {
                for(int i = lenS; i > 0; --i) {
                    dp[i] = dp[i-1] && ISMATCH(s[i-1], p[j]);
                }
                dp[0] = false;
            }
        }
        return dp[lenS];
    }
};

 



leetcode problem 10 Regular Expression Matching

标签:

原文地址:http://www.cnblogs.com/lysuns/p/4434569.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!