首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> C語言 >> C++ >> C++ 入門

LeetCode 正則表達式匹配:從暴力遞歸到動態規劃優化

     編輯:C++ 入門

題目背景

LeetCode Regular Expression Matching 是一道經典的高難度題目。給定字串 s 與模式 p,模式中包含 .(匹配任意單字符)與 *(前一字符出現零次或多次),判斷 s 是否完全匹配 p。

暴力遞歸解法

基本思路:從 s[i] 與 p[j] 開始遞歸匹配。

  • 情況 1:p[j+1] != '*'。若當前字符匹配(相等或 p[j]=='.'),遞歸檢查 (i+1, j+1);否則返回 false。
  • 情況 2:p[j+1] == '*'。令 k 為從 i 開始連續匹配 p[j] 的字符數,依次嘗試 (i, j+2), (i+1, j+2), …, (i+k, j+2),任一成功即返回 true。

時間複雜度最壞呈指數級,空間複雜度為遞歸棧深度 O(n)。

public boolean isMatch(String s, String p) {
    return helper(s, p, 0, 0);
}
private boolean helper(String s, String p, int i, int j) {
    if (j == p.length()) return i == s.length();
    if (j == p.length()-1 || p.charAt(j+1) != '*') {
        if (i == s.length() || (s.charAt(i) != p.charAt(j) && p.charAt(j) != '.')) return false;
        return helper(s, p, i+1, j+1);
    }
    // p.charAt(j+1) == '*'
    while (i < s.length() && (p.charAt(j) == '.' || s.charAt(i) == p.charAt(j))) {
        if (helper(s, p, i, j+2)) return true;
        i++;
    }
    return helper(s, p, i, j+2);
}

動態規劃優化

定義 dp[i][j] 表示 s 前 i 字符與 p 前 j 字符是否匹配(維度 (n+1)×(m+1))。外層循環遍歷模式 p,內層遍歷字串 s,避免重複計算。

  • p[j-1] != '*':dp[i][j] = dp[i-1][j-1] && (s[i-1]==p[j-1] || p[j-1]=='.')
  • p[j-1] == '*' 且 p[j-2] != '.':滿足以下任一即為 true:
    1. dp[i][j-2](* 匹配 0 次)
    2. dp[i-1][j] && s[i-1]==p[j-2](* 匹配 ≥1 次)
  • p[j-1] == '*' 且 p[j-2] == '.':.* 可匹配任意子串,若 dp[i][j-2] 或 dp[i-1][j] 為 true,則後續同列全為 true。

時間/空間複雜度均為 O(n²)。

public boolean isMatch(String s, String p) {
    if (s.isEmpty() && p.isEmpty()) return true;
    if (p.isEmpty()) return false;
    boolean[][] dp = new boolean[s.length()+1][p.length()+1];
    dp[0][0] = true;
    for (int j = 0; j < p.length(); j++) {
        if (p.charAt(j) == '*') {
            if (j > 0 && dp[0][j-1]) dp[0][j+1] = true;
            if (j < 1) continue;
            if (p.charAt(j-1) != '.') {
                for (int i = 0; i < s.length(); i++) {
                    if (dp[i+1][j] || (j>0 && dp[i+1][j-1]) ||
                        (i>0 && j>0 && dp[i][j+1] && s.charAt(i)==s.charAt(i-1) && s.charAt(i-1)==p.charAt(j-1)))
                        dp[i+1][j+1] = true;
                }
            } else {
                int i = 0;
                while (j>0 && i

總結

動態規劃通過備份中間結果將指數級遞歸降為多項式複雜度,是面試中常考的硬核題目。類似思路可應用於 Wildcard Matching 等變體。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved