https://leetcode.cn/problems/regular-expression-matching/desc...

三、动态规划版本

class Solution8 {
    public boolean isMatch(String str, String pat) {
        boolean match[][] = new boolean[str.length() + 1][pat.length() + 1];

        // init for s.length = 0;
        match[0][0] = true;
        // si和pi都作为substring的第二个参数的含义,其实际用到charAt得为i-1,i起点为1,终点为length+1
        for (int pi = 1; pi < pat.length() + 1; pi++) {
            boolean nextIsStar = pi < pat.length() && pat.charAt(pi) == '*';
            if (nextIsStar) {
                match[0][pi] = match[0][pi - 1];
                pi++;
                match[0][pi] = match[0][pi - 1];
            } else {
                break;
            }
        }

        for (int si = 1; si < str.length() + 1; si++) {
            for (int pi = 1; pi < pat.length() + 1; pi++) {
                char c = pat.charAt(pi - 1);
                boolean nextIsStar = pi < pat.length() && pat.charAt(pi) == '*';
                if (!nextIsStar) { // a-z
                    match[si][pi] = match[si - 1][pi - 1] && (c == str.charAt(si - 1) || c == '.'); // 因为pat没走完,可能被后面的 a*匹配到
                } else if (c == '.') { //.*
                    for (int k = si; k >= 0; k--) {
                        if (match[k][pi - 1]) {
                            match[si][pi] = true;
                            break;
                        }
                    }
                } else { // a-z*
                    if (match[si][pi - 1]) {
                        match[si][pi] = true;
                    } else {
                        for (int k = si; k >= 1; k--) {
                            if (str.charAt(k - 1) == c) { // 如果最后一位是a,循环直到 viSubStr.match(wholePat) || wholeStr.match(subPat)
                                if (match[k - 1][pi]) {
                                    match[si][pi] = true;
                                    break;
                                }
                            } else { // 否则,wholeStr.match(subPat)
                                match[si][pi] = match[k][pi - 1];
                                break;
                            }
                        }
                    }
                }
                if (nextIsStar) {
                    match[si][pi + 1] = match[si][pi];
                    pi++;
                }
            }
        }
        return match[str.length()][pat.length()];

    }
}

二、递归+缓存版本

Cache中的map可替换为Boolean[][],初始化大小决定了其花费的时间

class Solution6 {
    static char a = 'a';
    static char z = 'z';
    static char A = 'A';
    static char Z = 'Z';
    static char point = '.';
    static char star = '*';

    // 如何分类
    // a* .* . abc
    public boolean isMatch(String str, String pattern) {
        Cache cache = Cache.init(str, pattern);
        return cache.match();
    }

    static class Cache {
        Integer si = 0;
        Integer pi = 0;
        private String string;
        private String pattern;
        private Map<Integer, Map<Integer, Boolean>> map;

        public boolean match() {
            return match(string.length(), pattern.length());
        }

        private boolean match(Integer se, Integer pe) {
//            String str = string.substring(si, se);
//            String pat = pattern.substring(pi, pe);
            if (se <= si) {
                return emptyMatch(pi, pe);
            } else if (pe <= pi) {
                return false;
            }
            Boolean res = hitCache(se, pe);
            if (res != null) {
                return res;
            }
            res = false;
            char lastC = pattern.charAt(pe - 1);
            if (lastC == star) {  // .*
                for (int j = se; j >= si; j--) {
                    if (match(j, pe - 1)) {
                        res = true;
                        break;
                    }
                }
            } else if (lastC >= A && lastC <= Z) { // a* - z*
                for (int j = se - 1; j >= si; j--) {
                    if (string.charAt(j) == (char) (lastC + 32)) { // 如果最后一位是a
                        if (match(j, pe) || match(se, pe - 1)) { // 且 subStr.match(wholePat) || wholeStr.match(subPat)
                            res = true;
                            break;
                        }
                    } else {
                        res = match(se, pe - 1); // wholeStr.match(subPat)
                        break;
                    }
                }
            } else { // a-z || .
                res = (lastC == point || string.charAt(se - 1) == lastC) && match(se - 1, pe - 1);
            }
            putCache(se, pe, res);
            return res;
        }


        public Boolean hitCache(Integer se, Integer pe) {
            if (map.containsKey(se)) {
                return map.get(se).get(pe);
            } else {
                map.put(se, new HashMap<>());
                return null;
            }
        }

        public void putCache(Integer se, Integer pe, Boolean result) {
            map.get(se).put(pe, result);
        }

        private boolean emptyMatch(Integer pi, Integer pe) {
            for (int i = pi; i < pe; i++) {
                char c = pattern.charAt(i);
                if (c >= a && c <= z || c == point) {
                    return false;
                }
            }
            return true;
        }


        public static Cache init(String str, String pattern) {
            Cache cache = new Cache();
            cache.string = str;
            cache.pattern = formatPat(pattern);
            cache.map = new HashMap<>();
            return cache;
        }

        //*, A-Z,  a-z, .
        private static String formatPat(String pattern) {
            List<Character> parts = new ArrayList<>();
            for (int i = 0; i < pattern.length(); i++) {
                if (i + 1 < pattern.length() && pattern.charAt(i + 1) == star) {
                    if (pattern.charAt(i) == point) { // .*
                        parts.add(star);
                    } else { //  a* - z*
                        parts.add((char) (pattern.charAt(i) - 32));
                    }
                    i++;
                } else { // a-z .
                    parts.add(pattern.charAt(i));
                }
            }
            return parts.stream()
                .map(String::valueOf)
                .collect(Collectors.joining());
        }
    }

}

一、递归版本

class Solution3 {
    char a = 'a';
    char z = 'z';
    char A = 'A';
    char Z = 'Z';
    char point = '.';
    char star = '*';

    public boolean isMatch(String str, String pattern) {
        String newPattern = formatPat(pattern);
        return match(str, newPattern);
    }

    public boolean match(String str, String pat) {
        if (str.length() == 0) {
            return emptyMatch(pat);
        }
        if (pat.length() == 0) {
            return false;
        }
        char lastC = pat.charAt(pat.length() - 1);
        if (lastC == star) {  // .*
            for (int j = str.length(); j >= 0; j--) {
                if (match(sub(str, j), lessOne(pat))) {
                    return true;
                }
            }
            return false;
        } else if (lastC >= A && lastC <= Z) { // a* - z*
            for (int j = str.length() - 1; j >= 0; j--) {
                if (str.charAt(j) == (char) (lastC + 32)) {
                    if (match(sub(str, j), pat) || match(str, lessOne(pat))) {
                        return true;
                    }
                } else {
                    return match(str, lessOne(pat));
                }
            }
            return false;
        } else { // a-z || .
            return (lastC == point || str.charAt(str.length() - 1) == lastC) && match(lessOne(str), lessOne(pat));
        }
    }


    private boolean emptyMatch(String pat) {
        for (int i = 0; i < pat.length(); i++) {
            char c = pat.charAt(i);
            if (c >= a && c <= z || c == point) {
                return false;
            }
        }
        return true;
    }

    private String sub(String str, int endIdx) {
        if (endIdx <= 0) {
            return "";
        }
        return str.substring(0, endIdx);
    }

    private String lessOne(String str) {
        return sub(str, str.length() - 1);
    }

    //*, A-Z,  a-z, .
    private String formatPat(String pattern) {
        List<Character> parts = new ArrayList<>();
        for (int i = 0; i < pattern.length(); i++) {
            if (i + 1 < pattern.length() && pattern.charAt(i + 1) == star) {
                if (pattern.charAt(i) == point) { // .*
                    parts.add(star);
                } else { //  a* - z*
                    parts.add((char) (pattern.charAt(i) - 32));
                }
                i++;
            } else { // a-z .
                parts.add(pattern.charAt(i));
            }
        }
        StringBuilder sb = new StringBuilder();
        for (Character part : parts) {
            sb.append(part);
        }
        return sb.toString();
    }


}

零、测试用例

    public static void main(String[] args) {
        print("aab", "c*a*b", true);
        print("aa", "a", false);
        print("aa", "a*", true);
        print("ab", ".*", true);
        print("mississippi", "mis*is*ip*.", true);
        print("mississippi", "mis*is*p*.", false);
        print("aaa", "ab*a*c*a", true);
        print("a", ".*..a*", false);
        print("aab", "b.*", false);
        print("a", "..*", true);
        print("acbbcbcbcbaaaca", "ac*.a*ac*.*a", false);
    }

    private static void print(String str, String pattern, Boolean expectRes) {
        log.info("str {} pattern {} match {}, expect {}", str, pattern, new Solution8().isMatch(str, pattern), expectRes);
    }

lindsay_bubble
26 声望11 粉丝