您的位置:首页 > 其它

leetcode problem 10 Regular Expression Matching(动态规划)

2015-04-17 12:34 393 查看
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]
的空间代价的,但是由于状态转移方程中在获得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];
}
};

                                            
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: