zoukankan      html  css  js  c++  java
  • [LeetCode#44]Wildcard Matching

    Problem:

    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).
    
    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", "*") → true
    isMatch("aa", "a*") → true
    isMatch("ab", "?*") → true
    isMatch("aab", "c*a*b") → false

    Analysis:

    Key:
    For String problem, when the order of charcters in the string matters, we should try to take advantage of dynamic programming for future works. However, if it just care about (character set, could be permutated), we should try to take advantage of HashMap. 
    
    Sadlly, Even though you can come up with the idea of using two dimensional dynamic method to solve this problem, you can still be stucked with a complex implementation routine.
    
    For example, for this problem, you can come up with the following transitional equation:
    1. if checkboard[i-1][j-1] == true, and s.charAt(i) == s.charAt(j) || p.charAt(j) == '?' || p.charAt(j) == '*', we have checkboard[i][j].
    if (check_board[j] == true && (s.charAt(i) == p.charAt(j) || p.charAt(j) == '?')
        flag = true;
    
    2. if checkboard[i][j-1] == true, and s.charAt(j) == '*'
       if checkboard[i-1][j-1] == true, and s.charAt(j) == '*' (j could be used for matching " ")
       if checkboard[i-2][j-1] == true, ........................................................
     
    According to my prgramming stereotype, it is very hard to implement 
    if checkboard[i][j-1] == true, and s.charAt(j) == '*' (j could be used for matching " ")
    if checkboard[i-1][j-1] == true, and s.charAt(j) == '*' (j could be used for matching " ")
    if checkboard[i-2][j-1] == true, .....
    KEY: Since '*' can match any sequence of characters. 
    
    If you organize the loop through following way:
    for (int i = 0; i < s.length(); i++) {
        for (int j = p.length() - 1; j >= 0; j++) {
            ...
        }
    }
    How do you retrieve the state of preivous rows in one dimensional array? Impossible!
    Why not use j for outer lopp, and i for inner loop?
    for (int j = 0; j < p.length(); j++) {
        for (int i = s.length() - 1; i >= 0; i--) {
        ...
        }
    }
    
    
    Skill:
    a. properly use "" substring for both string. (This could lay a great foudation for our future inference)
    boolean[] check_board = new boolean[p.length()+1];
    check_board[0] = true; //cause "" = ""
    
    b. understand the start and direction of inference.
     for (int j = 0; j < p.length(); j++) {
        for (int i = s.length() - 1; i >= 0; i--) {
        ...
        }
     }
    Since we calculate the value for check_board[j][i], based on check_board[j-1][i],check_board[j-2][i] ...
    We must do the caculation from "right to left". 
    for (int i = s.length() - 1; i >= 0; i--)
    
    c. update the corner(boundary) column of the check_board. 
    true|flase|false|false|false
    ---------------------------
        |
        |
        |
        |
        |
    c.1 the first row of the matrix, must only have the first element equal to true. 
    c.2 the first column's value is pending. before the first non "*" charcter appears in the first column, all elements should be true. 
    heck_board[0] = check_board[0] && (p.charAt(j) == '*');
    
    d. use proper branch for organizing the program.
    Since "*" is quite different from other characters appeared in the pattern string p, we not we distinguish and cope both cases seperately. How about distinguish "*" from other characters.
    d.1 if p.charAt(j) != '*', 
    check_board[i+1] = check_board[i] && (s.charAt(i) == p.charAt(j) || p.charAt(j) == '?');   
    
    d.1 if p.charAt(j) == '*',
    as long as check_board[#][j-1] is true, all check_board[after #][j-1] shoud be true. Since '*' could equal to any sequence of characters. 
    if (p.charAt(j) != '*') {
        ...
    } else{
        int i = 0;
        while (i <= s.length() && !check_board[i]) {
            i++;
        }
        for (; i <= s.length(); i++) {
            check_board[i] = true;
        }               
    }
    Skil: we scan from check_board[i], but we acutally not change it!!! All elements are under same logic. How beautiful?
    
    
    
    Errors: (my first solution):
    public class Solution {
        public boolean isMatch(String s, String p) {
            if (s != null && p == null)
                return false;
            boolean[] check_board = new boolean[p.length()+1];
            check_board[0] = true;
            //be carefull with charAt when outside checking condition!
            if (p.length() > 0 && p.charAt(0) == '*') 
                check_board[1] = true;
            for (int i = 0; i < s.length(); i++) {
                for (int j = p.length() - 1; j >= 0; j++) {
                    if (check_board[j] == true && (s.charAt(i) == p.charAt(j) || p.charAt(j) == '?' || p.charAt(j) == '*'))
                        check_board[j+1] = true;
                    if (check_board[j+1] == true && p.charAt(j) == '*')
                        check_board[j+1] = true;
                }
                check_board[0] = false; //wrong too!!!!
            }
            return check_board[p.length()];
        }
    }
    
    Input:
    "aa", "a"
    Output:
    true
    Expected:
    false
    
    
    Problemetic part:
    for (int j = p.length() - 1; j >= 0; j++) {
        if (check_board[j] == true && (s.charAt(i) == p.charAt(j) || p.charAt(j) == '?' || p.charAt(j) == '*'))
            check_board[j+1] = true;
        if (check_board[j+1] == true && p.charAt(j) == '*')
            check_board[j+1] = true;
    }
    Reason: what if check_board[i][j+1] has not been udpated for true?
    if would contine to hold the same value as check_board[i-1][j+1].
    
    Wrong solution: <When you use one-dimensional array to save space, must rember to udpate state!!!>
    // The case is to hard to carry on any more!
    Fix:
    for (int j = p.length() - 1; j >= 0; j++) {
        boolean flag = false;
        if (check_board[j] == true && (s.charAt(i) == p.charAt(j) || p.charAt(j) == '?' || p.charAt(j) == '*'))
            flag = true;
        if (check_board[j+1] == true && p.charAt(j) == '*')
            flag = true;
        check_board[j+1] = flag;
    }

    Solution:

    public class Solution {
        public boolean isMatch(String s, String p) {
            if (s != null && p == null)
                return false;
            boolean[] check_board = new boolean[s.length()+1];
            check_board[0] = true;
            for (int j = 0; j < p.length(); j++) {
                if (p.charAt(j) != '*') {
                    for (int i = s.length() - 1; i >= 0; i--) {
                        check_board[i+1] = check_board[i] && (s.charAt(i) == p.charAt(j) || p.charAt(j) == '?');   
                    }
                } else{
                    int i = 0;
                    while (i <= s.length() && !check_board[i]) {
                        i++;
                    }
                    for (; i <= s.length(); i++) {
                        check_board[i] = true;
                    }               
                }
                check_board[0] = check_board[0] && (p.charAt(j) == '*');
            }
            return check_board[s.length()];
        }
    }
  • 相关阅读:
    iNeuOS工业互联平台,WEB组态(iNeuView)集成rtmp和websocket视频元件,支持海康、大华等摄像头实时显示视频
    MyBatis之TypeHandler用法
    视频监控安防专网事件预警运维系统开发方案
    Qmgo 开源了! 更好用的 Go 语言 MongoDB driver
    前端使用axios传递数组后端使用List接收
    jdk1.6手册java8中英手册java9英文手册.chm(下载)
    自动化运维工具Ansible (一)
    初级模拟电路:4-11 混合π模型
    简单体验一个高性能,简单,轻量的ORM库- Dapper (无依赖其它库,非常方便高效)
    Python计算大文件行数方法及性能比较
  • 原文地址:https://www.cnblogs.com/airwindow/p/4759172.html
Copyright © 2011-2022 走看看