10. Regular Expression Matching

题目:
LeetCode:10. Regular Expression Matching

描述:

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

大体意思和正则匹配很相似,但不同的是* 是匹配前一个字符的。开始的时候理解错了题意走了弯路,虽然还是可以做的。。。。。

分析:

1.暴力枚举的办法:

 // 思路:
// 1、s、p从0开始相互匹配,当且仅当p匹配至结尾时,s也匹配至结尾后才显示匹配成功;
// 2.1 判断p是否匹配至结尾,若为结尾判断s是否为结尾。
// 2.2 判断当前索引的下一字符是否为'*':
// 2.2.1 若下一字符不为'*',则判断当前字符是否匹配成功p[nIndexP] == '.' || p[nIndexP] == s[nIndexS]
// 2.2.1.1 当前字符匹配成功则两字符串索引累加,递归匹配下一字节是否匹配;
// 2.2.1.2 若匹配失败,返回匹配失败;
// 2.2.2 若下一字符为'*',则将递归匹配 nIndexP + 2 字符与 s字符串的剩余部分。
// 2.2.2.1 成功则匹配成功,失败则回溯当前状态;
// 2.2.2.2 失败回溯则,s字符串累加1后,继续重复2.2.2步骤。
// 2.2.2.3 直至* 将所有s中与前一字符相同的字符全部匹配,匹配p中'*'后剩余字符串与s剩余字符串递归2.1步骤
// 备注:若为正则表达式则此处为匹配任意字符都可以,而不是匹配p的前一字符
// 2.2.2 若下一字符为'*',则判断(p[nIndexP] == '.' || p[nIndexP] == s[nIndexS] && nIndexS < s.size()))
// 依次匹配s的字符,直至匹配到s字符不等于p当前字符或s结尾部分。
// 若下一字符为'*',则用 匹配 nIndexP + 2 字符与 s字符串的剩余部分进行匹配,若匹配成功,则成功。
// 反之累加s字符索引,右移一个位重复是
// 2.2.2.1 则判断当前字符是否相等 并且 nIndexS是否越界

2.使用动态规划的方法,讨论Si与Pi的匹配问题,列出状态转移方程,完成设计。由于对动态规划理解不够深刻,所以专门补习了一下,详细可参考白话算法之动态规划

代码:

思路一:递归方式,160ms左右

bool match(string s, string p, int nIndexS, int nIndexP)
{
    // p 是否匹配到结尾,当且仅当 s、p同时到结尾部分才匹配成功
    int nLenS = s.length();
    int nLenP = p.length();
    if (nIndexP == nLenP)
    {
        return nIndexS == nLenS;
    }
    if (p[nIndexP + 1] != '*')
    {
        if (p[nIndexP] == s[nIndexS] || p[nIndexP] == '.')
        {
            ++nIndexP;
            ++nIndexS;
            return match(s, p, nIndexS, nIndexP);
        }
        return false;
    }
    else
    {
        while (p[nIndexP] == s[nIndexS] || p[nIndexP] == '.' && nIndexS < nLenS)
        {
            if (match(s, p, nIndexS, nIndexP + 2))
            {
                return true;
            }
            // * 匹配掉相同字符
            ++nIndexS;
        }
        return match(s, p, nIndexS, nIndexP + 2);
    }
}
bool isMatch(string s, string p)
{
    return match(s, p, 0, 0);
}

思路二:动态规划方式

bool isMatch1(string s, string p) {
    int slen = s.size();
    int plen = p.size();
    vector<vector<bool>> dp(slen + 1, vector<bool>(plen + 1, false));
    dp[0][0] = true;
    for (int i = 0; i <= slen; ++i) {
        for (int j = 1; j <= plen; ++j) {
            if (p[j - 1] == '*') {
                dp[i][j] = dp[i][j - 2] || (i > 0 && (s[i - 1] == p[j - 2] || p[j - 2] == '.') && dp[i - 1][j]);
            }
            else dp[i][j] = i > 0 && dp[i - 1][j - 1] && (s[i - 1] == p[j - 1] || p[j - 1] == '.');
        }
    }
    return dp[slen][plen];
}

备注:
后续会补充对动态规划方法的解法,在本题中动态规划效率极高。

posted @ 2017-05-26 00:20  suilin  阅读(156)  评论(0编辑  收藏  举报