正则表达式匹配

关键步骤: 如何处理 通配符*

  1. s[i] == pattern[j] && pattern[j + 1] == '*', 可以匹配0次、1次或多次
  2. s[i] != pattern[j] && pattern[j + 1] == '*', 只能匹配0次

对于第二种情况是比较好处理的,只能匹配0次,将模式串的匹配指针向后移动2位即可。而对于第一种情况,我们需要对每一种匹配次数都去尝试,然后记录中间结果。

import java.util.HashMap;
import java.util.Map;

/**
 * 正则表达式匹配
 */
public class RegularMatch {
    private Map<String, Boolean> memSearch = new HashMap<>();

    public boolean regularMatch(String s, String pattern) {
        return dp(s, 0, pattern, 0);
    }

    /**
     * 匹配 s[i..] 与 pattern[j..]
     * @param s
     * @param i
     * @param pattern
     * @param j
     * @return
     */
    private boolean dp(String s, int i, String pattern, int j) {
        int m = s.length();
        int n = pattern.length();

        // 已经匹配到 模式串 的末尾, 检验文本是否匹配到末尾
        if (j == n) {
            return i == m;
        }

        // 已经匹配到 文本的 末尾, 检验之后的模式串是否能匹配空白串
        if (i == m) {
            // 剩下奇数个字符, 无法满足要求
            if ((n - j) % 2 == 1) {
                return false;
            }

            for (; j + 1 < n; j += 2) {
                if (pattern.charAt(j + 1) != '*') {
                    return false;
                }
            }

            return true;
        }

        // 记忆化存储已经搜索过的路径
        String key = i + "," + j;
        if (memSearch.containsKey(key)) {
            return memSearch.get(key);
        }

        /**
         * 情况1: s[i] == pattern[j] && pattern[j + 1] == '*', 匹配0次或多次
         * 情况2: s[i] == pattern[j] && pattern[j + 1] != '*', 正常匹配1次
         * 情况3: s[i] != pattern[j] && pattern[j + 1] == '*', 匹配0次
         * 其他情况: 无法匹配
         */
        boolean res = false;
        if (s.charAt(i) == pattern.charAt(j) || pattern.charAt(j) == '.') {
            if (j < n - 1 && pattern.charAt(j + 1) == '*') {
                // 通配符匹配0次, 或通配符匹配1次, 向下递归
                res = dp(s, i, pattern, j + 2) || dp(s, i + 1, pattern, j);
            }
            else {
                // 正常匹配1次
                res = dp(s, i + 1, pattern, j + 1);
            }
        }
        else {
            // 通配符匹配0次
            if (j < n - 1 && pattern.charAt(j + 1) == '*') {
                res = dp(s, i + 1, pattern, j + 2);
            }
        }

        memSearch.put(key, res);
        return res;
    }

    public static void main(String[] args) {
        RegularMatch r = new RegularMatch();
        System.out.println(r.regularMatch("a", "ab*"));
    }
}
posted @ 2023-06-29 20:52  ylyzty  阅读(13)  评论(0编辑  收藏  举报