LintCode 154: Regular Expression Matching (经典题)

这题有两个解法:

  1. DFS+Memorization
  2. DP

DFS+Memorization的解法和wild matching相似。需要注意的地方有:

  1. 需要检查p[pIndex + 1] 而不是 p[pIndex]。这是因为‘*’ 或 ‘.’ 在char的后面一个。

  2. 如果p[pIndex + 1] 是’*‘, 并且pIndex + 1 < p.size(),那么需要检查s[sIndex]和p[pIndex]是否match。如果不match,还有第二次机会,因为’*'可以表示0个字符。

For example, s = “abc”, p = “a*abc”
s[1] and p[0…1] matches fails, but we can compare s[0] and p[2] and it passes.

  1. 如果p[pIndex + 1]是‘*‘, 并且pIndex +1= p.size(),那么’*‘退化为’.',所以该情况可以放到else分支处理。

代码如下:

class visitedMemo {
public:
    bool visited;
    bool memo;
    visitedMemo(bool v = false, bool m = false) : visited(v), memo(m) {}
};

class Solution {
public:
    /**
     * @param s: A string 
     * @param p: A string includes "." and "*"
     * @return: A boolean
     */
    bool isMatch(string &s, string &p) {
        if (s.empty() || p.empty()) return false;
        
        //define vm[s.size()][p.size()]
        vector<vector<visitedMemo>> vm;
        vm.resize(s.size(), vector<visitedMemo>(p.size()));   

        return helper(s, 0, p, 0, vm); 
    }

    bool helper(string const &s, int sIndex, string const &p, int pIndex, vector<vector<visitedMemo>> &vm) {

        // if p reaches the end (pos is the last char + 1) first, s should also reaches the end
        if (pIndex  == p.size()) {
            return (sIndex == s.size());    
        }

        // if s reaches the end first
        // for example, s = "abb", p = "a**?*?*..." or p = "a*"
        if (sIndex == s.size()) {
            for (int i = pIndex; i < p.size(); i += 2) {  //note i+=2 as it can be abbz*x*y*...
                if (((i + 1) >= p.size()) || (p[i + 1] != '*')) return false;
            }
            return true;
        }

        if (vm[sIndex][pIndex].visited) return vm[sIndex][pIndex].memo;

        vm[sIndex][pIndex].visited = true;
        
        if ((pIndex + 1 < p.size()) && (p[pIndex + 1] == '*')) {
            if ((s[sIndex] == p[pIndex]) || (p[pIndex] == '.')) 
                // * presents one or more preceding element
                vm[sIndex][pIndex].memo = helper(s, sIndex + 1, p, pIndex, vm);
            
            //for example: s = "abc", p = "a*abc"
            //s[1] and p[0..1] match fail, but we have second chance.
            if (!vm[sIndex][pIndex].memo) 
                // * represents zero preceding element
                vm[sIndex][pIndex].memo = helper(s, sIndex, p, pIndex + 2, vm);
        #if 0
            if (helper(s, sIndex, p, pIndex + 2, vm)) 
                vm[sIndex][pIndex].memo = true;
            else {
                if ((s[sIndex] == p[pIndex]) || (p[pIndex] == '.')) 
                    vm[sIndex][pIndex].memo = helper(s, sIndex + 1, p, pIndex, vm);
                else
                    vm[sIndex][pIndex].memo = false;
            }
        #endif    
        } else {
            if ((s[sIndex] == p[pIndex]) || (p[pIndex] == '.'))
                vm[sIndex][pIndex].memo = helper(s, sIndex + 1, p, pIndex + 1, vm);
            else
                vm[sIndex][pIndex].memo = false;
        }

        return vm[sIndex][pIndex].memo;
    }
};
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值