zoukankan      html  css  js  c++  java
  • [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)
    Example
    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


    For s[0 ~ i] and p[0 ~ j], we have the following cases.

    1. s[i] == p[j] or p[j] == '.' ,   reduce the problem to s[0 ~ i - 1] and p[0 ~ j - 1];

    2. p[j] == '*', 

     a.  s[i] == p[j - 1] or p[j - 1] == '.'   : reduce to s[0 ~ i] and p[0 ~ j - 2] for 0 occurence of p[j - 1];  or reduce to s[0 ~ i - 1] and p[0 ~ j] for 1 occurence of p[j - 1].

        b.  s[i] != p[j - 1] :  reduce to s[0 ~ i] and p[0 ~ j - 2] for 0 occurence of p[j - 1].

    3. all other cases s and p do not match. 

     

    We can solve this problem based the above analysis both recursively and by dynamic programming. 

    Solution 1. Recursion

     1 public class RegularExpressionMatching {
     2     public boolean isMatchRecursion(String str, String pattern) {
     3         if(str == null || pattern == null) {
     4             return false;
     5         }
     6         String newPattern = pattern.replaceAll("(\*){2,}", "*"); 
     7         return matchHelper(str, str.length() - 1, newPattern, newPattern.length() - 1);
     8     }
     9     private boolean matchHelper(String str, int idx1, String pattern, int idx2) {
    10         if(idx1 < 0 && idx2 < 0 || idx1 < 0 && idx2 <= 1 && pattern.charAt(idx2) == '*') {
    11             return true;
    12         }
    13         else if(idx1 < 0 && idx2 >= 0 || idx1 >= 0 && idx2 < 0) {
    14             return false;
    15         }
    16         if(pattern.charAt(idx2) == '.' || str.charAt(idx1) == pattern.charAt(idx2)) {
    17             return matchHelper(str, idx1 - 1, pattern, idx2 - 1);
    18         }
    19         else if(pattern.charAt(idx2) == '*') {
    20             if(idx2 > 0 && (pattern.charAt(idx2 - 1) == str.charAt(idx1) || pattern.charAt(idx2 - 1) == '.')) {
    21                 return matchHelper(str, idx1, pattern, idx2 - 2) || matchHelper(str, idx1 - 1, pattern, idx2);
    22             }
    23             else {
    24                 return matchHelper(str, idx1, pattern, idx2 - 2);
    25             }
    26         }
    27         return false;
    28     }
    29     public static void main(String[] args) {
    30         RegularExpressionMatching test = new RegularExpressionMatching();
    31         System.out.println(test.isMatchRecursion("", ""));    //true
    32         System.out.println(test.isMatchRecursion("", "*"));    //true
    33         System.out.println(test.isMatchRecursion("aa", "a"));    //false
    34         System.out.println(test.isMatchRecursion("aa", "aa"));    //true
    35         System.out.println(test.isMatchRecursion("aaa", "aa"));    //false
    36         System.out.println(test.isMatchRecursion("aa", "*"));    //false
    37         System.out.println(test.isMatchRecursion("aa", "**"));    //false
    38         System.out.println(test.isMatchRecursion("aa", "a*"));    //true
    39         System.out.println(test.isMatchRecursion("ab", ".*"));    //true
    40         System.out.println(test.isMatchRecursion("aab", "*a.b"));    //true        
    41     }
    42 }

    Solution 2. Dynamic Programming 

    Initialization: 

    T[0][0] = true;  When both s and p are empty string, the match result should return true.

    When s is empty, there is also another case of p that matches the empty string.  If each letter a-z or . is followed by *, like a*b*c*, then taking 0 occurence of each letter matches empty string.

     1 public boolean isMatchDp(String str, String pattern) {
     2     if(str == null || pattern == null) {
     3         return false;
     4     }
     5     String newPattern = pattern.replaceAll("(\*){2,}", "*"); 
     6     boolean[][] T = new boolean[str.length() + 1][newPattern.length() + 1];
     7     T[0][0] = true;
     8     for(int i = 1; i <= newPattern.length(); i++) {
     9         if(i == 1 && newPattern.charAt(i - 1) == '*') {
    10             T[0][i] = true;
    11         }
    12         else if(newPattern.charAt(i - 1) == '*') {
    13             T[0][i] = T[0][i - 2];
    14         }
    15     }
    16     for(int i = 1; i <= str.length(); i++) {
    17         for(int j = 1; j <= newPattern.length(); j++) {
    18             if(str.charAt(i - 1) == newPattern.charAt(j - 1) || newPattern.charAt(j - 1) == '.') {
    19                 T[i][j] = T[i - 1][j - 1];
    20             }
    21             else if(newPattern.charAt(j - 1) == '*') {
    22                 if(j == 1) {
    23                     T[i][j] = false;
    24                 }
    25                 else {
    26                     T[i][j] = T[i][j - 2];
    27                     if(str.charAt(i - 1) == newPattern.charAt(j - 2) || newPattern.charAt(j - 2) == '.'){
    28                         T[i][j] |= T[i - 1][j];
    29                     }
    30                 }
    31             }
    32             else {
    33                 T[i][j] = false;
    34             }
    35         }
    36     }
    37     return T[str.length()][newPattern.length()];
    38 }

    Related Problems 

    Wildcard Matching



  • 相关阅读:
    期权波动率模型及交易策略分析
    k阶原点距和k阶中心距各是说明什么数字特征
    在Linux中监视IO性能
    NUMA微架构
    Web网站的几个QPS
    Elasticsearch与Solr 选型
    相关连接(后续更新)
    linux_基本命令使用(后续更新)
    centos7.5安装kafka(支持外部连接)
    centos7.5单机安装安装zookeeper
  • 原文地址:https://www.cnblogs.com/lz87/p/7442429.html
Copyright © 2011-2022 走看看