leetcode10 正则表达式匹配(递归,动态规划)

  •  用递归的算法
  •  
    static const auto __speedup_ = []() {
        std::cout.sync_with_stdio(false);
        std::cin.tie(nullptr);
        return 0;
    }();
    
    /*
        用递归的算法:注意边界条件的讨论
    
    
        原问题如下:
        Given an input string (s) and a pattern (p), 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).
    
        Note:
    
        s could be empty and contains only lowercase letters a-z.
        p could be empty and contains only lowercase letters a-z, and characters like . or *.
    */
    class Solution {
    public:
        // 用p匹配s
        bool isMatch(string s, string p) {
            // p为空时的讨论
            if (!p.length() && !s.length())
                return true;
            if (!p.length() && s.length() > 0)
                return false;
    
            // s为空时的讨论,只有p为 .*.*.*.*.* 的形式时才能匹配
            if (!s.length())
            {
                if (p.length() % 2 == 1)  return false;
    
                int i = 1;
                while (i < p.length() && p[i] == '*')
                {
                    i += 2;
                }
                if (i == p.length() + 1) return true;
                else return false;
            }
    
            // p[1]为*时,用p+2匹配s+0,s+1,s+2,s+3…………,成功返回true,失败返回false
            int i = -1;
            if (p.length() >=2 && p[1] == '*')
            {
                do {
                    // 当++i为len+1时截取字符串才会越界报错,但是++i为len时截取的子串为空就已经返回结果了,所以永远没有机会截取len+1
                    if (isMatch(s.substr(++i), p.substr(2)))
                        return true;
                    // 匹配失败且i已经为len了,即p+2匹配到s的最后了任然匹配失败,return false
                    else if (i == s.length())
                        return false;
                    // 由于上面的++i截取到len时就会return退出,所以s[i]也永远不会越界
                } while ((s[i] == p[0] || p[0] == '.'));
                return false;
            }
            // p[1]不为*时    
            else
            {
                if (s[0] == p[0] || p[0] == '.')
                    return isMatch(s.substr(1), p.substr(1));
                else
                    return false;
            }
        }
    };

     

  • 用动态规划的算法
  • /*
        用动态规划的算法:边界、越界问题最后统一讨论
    
    
        原问题如下:
        Given an input string (s) and a pattern (p), 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).
    
        Note:
    
        s could be empty and contains only lowercase letters a-z.
        p could be empty and contains only lowercase letters a-z, and characters like . or *.
    */
    class Solution {
    public:
        // 用p匹配s
        bool isMatch(string s, string p) {
            // match[i][j]==true 表示s的前i位和p的前j位是匹配的
            vector< vector<bool> > match(s.length() + 3, vector<bool>(p.length() + 3, false));
            
            // 边界条件为i=0 j=0 j=1
            // j=0时p为空串,只能匹配空串,其他默认为false
            match[0][0] = true;
            // j=1时p只有一个字符,只能匹配一个字符,其他全部为false
            match[1][1] = s[0] == p[0] || p[0] == '.';
            // i=0时s为空串,p只有类似a*b*c*d*这样的形式才可以成功匹配
            for (int j = 2; j < p.length() + 1; j += 2)
                // 前0位和前j-2位是匹配的,且第j位是*
                match[0][j] = match[0][j - 2] && p[j - 1] == '*';
    
    
            // i表示s的前i位,j表示p的前j为
            for (int i = 1; i < s.length() + 1; i++)
                for (int j = 2; j < p.length() + 1; j++)
                {
                    if (p[j - 1] != '*')
                        // 前i-1位和前j-1位是匹配的,且第i位和第j位是匹配的
                        match[i][j] = match[i - 1][j - 1] && (s[i - 1] == p[j - 1] || p[j - 1] == '.');
                    else
                        //当p[j-1]出现0次时,前i位和前j-2位是匹配的
                        //当p[j-1]出现1次或多次时,第i位一定匹配第j-1位,且前i-1位一定和前j位是匹配的。
                        match[i][j] = match[i][j - 2] || match[i - 1][j] && (s[i - 1] == p[j - 2] || p[j - 2] == '.');
                }
            return match[s.length()][p.length()];
        }
    };

     

  • 1234234
posted on 2018-04-28 14:29  jkn1234  阅读(3423)  评论(0编辑  收藏  举报