LeetCode 10. Regular Expression

作者: 余空啊 | 来源:发表于2018-01-19 16:55 被阅读84次

    Regular Expression Matching

    1、原题

    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

    原题链接

    一定要 仔细看题仔细看题

    • .* 是一体的,代表可以匹配任意个任意的字符
    • a* 也一体的 看第七个case,把c*看成匹配一体、把 a*也看成一体的,那么当c*匹配空字符并且a*匹配两个字符a,那么aab跟c*a*b就是匹配的 所以输出了 true

    2、解题思想

    这题可以通过 动态规划 解决,

    首先我们可以 定义个 boolean match[i][j]
    代表 待匹配串s中从0...i的子串与原串0...就的子串的匹配结果 true 匹配成功 false 匹配失败。

    接下来就是动态规划的流程了。

    1、 找边界条件

    case 1.1、 i == 0 && j == 0

    i=0j=0 的时候 那么 match[i][j] = true 这毫无疑问的 两个空串匹配肯定是 true

    case 1.2、i == 0 && j > 2 && p[j-2] == '*'

       i == 0 && j > 2 && p[j-2] == '*' ;
       match[i][j] == match[i][j-2] 
    

    这为什么呢 因为直接我说过 .* 或者 a* 可以匹配匹配任意个任意的字符
    那么就是说 s=""p=".*"或者 p="a*" 是匹配值 为什么 .* 可以匹配空字符

    case 1.3、 i != 0 && j == 0

    i=0j!=0 的时候 那么 match[i][j] = false 因为待匹配串长度不为0 但是原串长度是0 这是无法匹配上的 所以是false

    2、 找状态转移方程

    case 2.1 p[j] != '*"

    match[i+1][j+1] = match[i][j] and (s[i] == p[j] or p[j] == '.' )

    这种情况最好理解就不多解释。

    case 2.1 p[j] == '*"

    因为我之前说过 .* a* c*是一体的

    那么它们可以匹配0个或者1个或者多个字符

    我们一个一个分情况考虑

    a、 当前*匹配0个字符
    match[i+1][j+1] = match[i+1][j-1]
    举栗
    s="aaa" p="aaab*" ===> true
    b、 当前*匹配1个字符
    match[i+1][j+1] = match[i][j-1] && (s[i] == p[j-1] || p[j-1] == '.')
    举栗
    s="aa" p="a*" ===>true
    b、 当前*匹配多个字符
    match[i+1][j+1] = match[i][j+1] && (s[i] == p[j-1] || p[j-1] == '.')
    举栗
    s="aaaa" p="a*" ===>true

    3、 编码

    下面贴一下我leetocode ac的代码

    public static boolean isMatch(String s, String p) {
    
            boolean[][] match = new boolean[s.length() + 1][p.length() + 1];
    
            match[0][0] = true;
            for (int i = 1; i < p.length(); i++) {
                if (p.charAt(i) == '*') {
                    match[0][i + 1] = match[0][i - 1];
                }
            }
            for (int i = 1; i < s.length() + 1; i++) {
                for (int j = 1; j < p.length() + 1; j++) {
                    if (p.charAt(j - 1) != '*') {
                        match[i][j] = match[i - 1][j - 1] && (s.charAt(i - 1) == p.charAt(j - 1) || p.charAt(j - 1) == '.');
                    } else if (p.charAt(j - 1) == '*') {
                        // *匹配0个
                        match[i][j] = (match[i ][j - 2]
                                //   *匹配1个
                                || (match[i - 1][j - 2] && (s.charAt(i - 1) == p.charAt(j - 2) || p.charAt(j - 2) == '.'))
                                //   *匹配多个
                                || (match[i - 1][j] && (s.charAt(i - 1) == p.charAt(j - 2) || p.charAt(j - 2) == '.'))
                        );
                    }
    
                }
            }
    
            return match[s.length()][p.length()];
    
        }
    

    4、 总结

    其实这题也可以用递归写出来 但是时间复杂度是指数级 用dp的时间复杂度是O(n^2),
    最后如果写的有什么不足之处欢迎指定。

    相关文章

      网友评论

        本文标题:LeetCode 10. Regular Expression

        本文链接:https://www.haomeiwen.com/subject/gmzooxtx.html