• LeetCode第[44]题(Java):Wildcard Matching


    题目:通配符匹配

    难度:hard

    题目内容

    Given an input string (s) and a pattern (p), implement wildcard pattern matching with support for '?' and '*'.

    '?' Matches any single character.
    '*' Matches any sequence of characters (including the empty sequence).
    

    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 *.

    翻译:给定一个输入字符串(s)和一个模版(p),实现通配符模式匹配,并支持“?””和“*”。

    ”?匹配任何一个字符。

    “匹配任何字符序列(包括空序列)。

    匹配应该覆盖整个输入字符串(而不是部分)。

     

    注意:

    s可以是空的,并且只包含小写字母a-z。

    p可以是空的,只包含小写字母a-z,还有?或*。

    我的思路:此题和第10题很像:Regular Expression Matching,但是10题里是' . '和 ' * ',这里是' ? ' 和 ‘ * ’,

    ' . '和 ' ? ' 意义相对应,但是  ' * ' 表示意义不同,第10题是只代表个数,本题是代表任何序列,于是把第十题代码修改下:

    1、first_match要加上 pattern.charAt(0) == '*' 的情况;

    2、后面分两种互斥情况A、B:

    A:以 * 匹配:(此时又分两种相容情况

       a1:*没有匹配任何的字符

       a2:*匹配上此字符

      A情况的结果为  a1 || a2

    B:没*:

      当前匹配结果 && 下一个元素和下一个pattern的匹配结果。

    我的代码:

     1     public boolean isMatch(String text, String pattern) {
     2         if (pattern.isEmpty()) return text.isEmpty();
     3         boolean first_match = (!text.isEmpty() && 
     4                                (pattern.charAt(0) == text.charAt(0) || pattern.charAt(0) == '?' || pattern.charAt(0) == '*'));
     5         
     6         if (pattern.charAt(0) == '*'){
     7             return (isMatch(text, pattern.substring(1)) || 
     8                     (isMatch(text.substring(1), pattern)));
     9         } else {
    10             return first_match && isMatch(text.substring(1), pattern.substring(1));
    11         }
    12     }

    结果1614 / 1808 test cases passed.   

    Last executed input:   "aaabbbaabaaaaababaabaaabbabbbbbbbbaabababbabbbaaaaba"   "a*******b"

    ------Time Limit Exceeded------

    看来那个方法是可行的,可能是因为用了递归,中间太多***导致子递归太多,所以运行太慢。

    答案代码

     1     public boolean isMatch(String s, String p) {
     2       int m = s.length(), n = p.length();
     3       char[] sc = s.toCharArray();
     4       char[] pc = p.toCharArray();
     5       boolean[][] dp = new boolean[m + 1][n + 1];
     6       dp[0][0] = true;
     7       for(int j = 1; j < n + 1; j++){
     8         if(pc[j - 1] == '*') dp[0][j] = dp[0][j - 1]; 
     9       }   
    10       
    11       for(int i = 1; i < m + 1; i++){
    12         for(int j = 1; j < n + 1; j++){
    13           if(pc[j - 1] == sc[i - 1] || pc[j - 1] == '?'){
    14             dp[i][j] = dp[i - 1][j - 1];
    15           } else if(pc[j - 1] == '*'){
    16             dp[i][j] = dp[i - 1][j] || dp[i][j - 1];
    17           } else {
    18             dp[i][j] = false;
    19           }
    20         }
    21       }
    22       return dp[m][n];
    23     }

    答案复杂度:O(M*N)

    答案思路:使用一个二维数组对每个点的匹配状态进行记录,后面点的匹配状态取决于当前匹配和之前匹配,所以最后一个点的匹配状态就是整个匹配结果。

    数组的行列分别为pattern,str

    算法主要分两部分:

    1、给第0行和第0列赋值:

      第0列——除了第一个为true以外都为默认值false;

      第0行——如果pattern某个位置为*,则此时对应第0行的值等于前面一个的值,否则取默认值false。

    2、从第第1行第1列的元素开始:

      如果当前str值与pattern的值直接匹配上(或者匹配?)则二维数组此值直接取上一个“元素”的匹配结果:【i-1】【j-1】

      如果当前str值与pattern的值是靠‘’*‘’才匹配上,则二维数组此值等于

        (*没有匹配上此字符 || *匹配上此字符)==(这个元素和上一个pattern结果 || 这一个pattern和上一个元素的结果)

      以上两者都不是,则取默认值false

    eg. pattern = *a**a    str = bbaa

    bp[][]=   ' '       *      a       *      *       a

    '' [true, true, false, false, false, false]
    b [false, true, false, false, false, false]
    b [false, true, false, false, false, false]
    a [false, true, true, true, true, false]
    a [false, true, true, true, true, true]

    结论:第二种(答案)方法虽然不错,但是理解起来太麻烦,不过也很好记,记住思路也行。。。

       在一般的面试或者笔试中使用第一种(我写的)方法足以应对。

  • 相关阅读:
    LAMP环境搭建
    Httpd
    MySQL常用配置和性能压力测试:MySQL系列之十五
    MySQL的高可用实现:MySQL系列之十四
    MySQL的复制:MySQL系列之十三
    备份与恢复:MySQL系列之十二
    日志记录:MySQL系列之十一
    事务隔离实现并发控制:MySQL系列之十
    SpringMVC上传文件(图片)并保存到本地
    W10如何开启LinuxBash及安装Ubuntu
  • 原文地址:https://www.cnblogs.com/Xieyang-blog/p/9006832.html
Copyright © 2020-2023  润新知