最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

動(dòng)態(tài)遞歸之正則表達(dá)式實(shí)戰(zhàn)案例(含Java代碼)

 更新時(shí)間:2026年05月08日 10:10:09   作者:納蘭青華  
正則表達(dá)式是對(duì)字符串的一種描述方法,即使用特定的信息來描述字符串格式的一種方式,這篇文章主要介紹了動(dòng)態(tài)遞歸之正則表達(dá)式的相關(guān)資料,文中通過代碼介紹的非常詳細(xì),需要的朋友可以參考下

題目:正則表達(dá)式

給你一個(gè)字符串 s 和一個(gè)字符規(guī)律 p,請(qǐng)你來實(shí)現(xiàn)一個(gè)支持 ‘.’ 和 ‘*’ 的正則表達(dá)式匹配。

‘.’ 匹配任意單個(gè)字符
‘*’ 匹配零個(gè)或多個(gè)前面的那一個(gè)元素

所謂匹配,是要涵蓋 整個(gè) 字符串 s 的,而不是部分字符串。

示例 1:

輸入:s = “aa”, p = “a”
輸出:false
解釋:“a” 無法匹配 “aa” 整個(gè)字符串。

示例 2:

輸入:s = “aa”, p = “a*”
輸出:true
解釋:因?yàn)?‘*’ 代表可以匹配零個(gè)或多個(gè)前面的那一個(gè)元素, 在這里前面的元素就是 ‘a’。因此,字符串 “aa” 可被視為 ‘a’ 重復(fù)了一次。

示例 3:

輸入:s = “ab”, p = “."
輸出:true
解釋:".” 表示可匹配零個(gè)或多個(gè)(‘*’)任意字符(‘.’)。

提示:

1 <= s.length <= 20
1 <= p.length <= 20
s 只包含從 a-z 的小寫字母。
p 只包含從 a-z 的小寫字母,以及字符 . 和 *。

保證每次出現(xiàn)字符 * 時(shí),前面都匹配到有效的字符

題解

方法一:帶記憶化遞歸

思路:

遞歸函數(shù) match(i, j) 表示字符串 s 從 i 開始到末尾的子串和模式 p 從 j 開始到末尾的子串是否匹配。
考慮以下情況:

  • 如果 j 已經(jīng)到達(dá) p 的末尾,那么只有當(dāng) i 也到達(dá) s 的末尾才匹配成功。
  • 首先檢查當(dāng)前第一個(gè)字符是否匹配:first_match = (i < s.length()) 且 (s.charAt(i) == p.charAt(j) 或 p.charAt(j) == ‘.’)
  • 如果下一個(gè)字符是 ‘*’ (即 j+1 < p.length() 且 p.charAt(j+1)==‘*’),那么有兩種情況:
          a. 匹配0個(gè)前面的字符:則跳過模式中的"x*"(即j+2),繼續(xù)匹配 match(i, j+2)
          b. 匹配1個(gè)或多個(gè)前面的字符:在第一個(gè)字符匹配的前提下,匹配s的下一個(gè)字符,模式保持不變(因?yàn)?可以匹配多個(gè)),即 match(i+1, j)
  • 否則,如果沒有’*',那么當(dāng)前字符必須匹配,然后遞歸匹配剩下的部分:match(i+1, j+1)
          但是注意:遞歸可能會(huì)出現(xiàn)重復(fù)子問題,所以效率可能不高,但作為解決方案之一。
public class RegularExpMatch {
    // 使用Map存儲(chǔ)已計(jì)算的結(jié)果,避免重復(fù)計(jì)算
    private Map<String, Boolean> memo = new HashMap<>();
    public boolean isMatch(String s, String p) {
        return dp(0, 0, s, p);
    }
    private boolean dp(int i, int j, String s, String p) {
        // 生成唯一鍵值對(duì),用于記憶化存儲(chǔ)
        String key = i + "," + j;
        if (memo.containsKey(key)) {
            return memo.get(key);
        }
        // 模式串已用完
        if (j == p.length()) {
            return i == s.length();
        }
        // 檢查當(dāng)前字符是否匹配
        boolean firstMatch = (i < s.length()) &&
                (s.charAt(i) == p.charAt(j) || p.charAt(j) == '.');
        boolean result;
        // 處理'*'的情況(需要確保j+1不越界)
        if (j + 1 < p.length() && p.charAt(j + 1) == '*') {
            // 兩種情況:
            //1. 匹配0個(gè)字符(跳過當(dāng)前字符和*)即匹配0次,不消耗任何字符串字符
            //2. 匹配1個(gè)或多個(gè)字符(繼續(xù)匹配)
            result = dp(i, j + 2, s, p) || (firstMatch && dp(i + 1, j, s, p));
        } else {
            // 沒有'*',正常匹配下一個(gè)字符
            result = firstMatch && dp(i + 1, j + 1, s, p);
        }
        // 存儲(chǔ)計(jì)算結(jié)果   
        memo.put(key, result);
        return result;
    }
}

方法二:動(dòng)態(tài)規(guī)劃

  • 初始化:空字符串匹配空模式
  • 處理模式開頭可能的"x*"匹配空字符串的情況
  • 狀態(tài)轉(zhuǎn)移分三種情況:
    • 普通字符匹配
    • '.'匹配任意字符
    • '*'的兩種處理方式(匹配0次或多次)
public boolean isMatch(String s, String p) {
   int m = s.length(), n = p.length();
   // dp[i][j]表示s的前i個(gè)字符和p的前j個(gè)字符是否匹配
   boolean[][] dp = new boolean[m + 1][n + 1];
   // 空字符串匹配空模式
   dp[0][0] = true;
   // 處理模式開頭可能有 "a*" 或 ".*" 的情況(匹配空字符串)
   for (int j = 2; j <= n; j++) {
       if (p.charAt(j - 1) == '*') {
           dp[0][j] = dp[0][j - 2]; // 跳過 "x*" 模式
       }
   }
   for (int i = 1; i <= m; i++) {
       for (int j = 1; j <= n; j++) {
           char sc = s.charAt(i - 1);
           char pc = p.charAt(j - 1);
           // 當(dāng)前字符匹配
           if (sc == pc || pc == '.') {
               //如果當(dāng)前字符匹配,此時(shí)的值為去掉當(dāng)前字符后是否匹配的值
               dp[i][j] = dp[i - 1][j - 1];
           }
           // 處理 '*' 的情況
           else if (pc == '*') {
               char prev = p.charAt(j - 2); // '*' 前面的字符,注意i和j表示的是dp表的下標(biāo),不是字符串下標(biāo),字符值下標(biāo)還需要-1
               // 1. 匹配0個(gè)字符(跳過 "x*" 模式)
               dp[i][j] = dp[i][j - 2];
               // 2. 匹配1個(gè)或多個(gè)字符(如果前一個(gè)字符匹配)
               if (prev == '.' || prev == sc) {
                   dp[i][j] = dp[i][j] || dp[i - 1][j]; //表示如果匹配0個(gè)字符成立就直接返回true了,否則再匹配1個(gè)或多個(gè)字符
               }
           }
       }
   }
   return dp[m][n];
}

考慮字符串 s = “abcde” 和模式 p = “abcc*d*.*de”,我們使用動(dòng)態(tài)規(guī)劃來解決匹配問題。動(dòng)態(tài)規(guī)劃表如下:
dp[i][j] 表示 s 的前 i 個(gè)字符與 p 的前 j 個(gè)字符是否匹配。

s\p01:a2:b3:c4:c5:*6:d7:*8:.9:*10:d11:e
0TFFFFFFFFFFF
1:aFTFFFFFFFFFF
2:bFFTFFFFFFFFF
3:cFFFTFTFTFTFF
4:dFFFFFFTTFTTF
5:eFFFFFFFFFFFT

總結(jié):

匹配0真的難繃,匹配0個(gè)我以為只是’*‘沒了但其前面的元素還在,結(jié)果是’*'和前面一個(gè)元素都沒了?。。?!

到此這篇關(guān)于動(dòng)態(tài)遞歸之正則表達(dá)式的文章就介紹到這了,更多相關(guān)動(dòng)態(tài)遞歸之正則表達(dá)式內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • SpringBoot集成Nacos實(shí)現(xiàn)注冊(cè)中心與配置中心流程詳解

    SpringBoot集成Nacos實(shí)現(xiàn)注冊(cè)中心與配置中心流程詳解

    這篇文章主要介紹了SpringBoot集成Nacos實(shí)現(xiàn)注冊(cè)中心與配置中心流程,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)吧
    2023-02-02
  • Java中將String類型轉(zhuǎn)換為int類型的五種方法及常見問題分析

    Java中將String類型轉(zhuǎn)換為int類型的五種方法及常見問題分析

    在Java中將String類型轉(zhuǎn)換為int類型是一個(gè)常見的操作,因?yàn)樵趯?shí)際開發(fā)中,我們經(jīng)常需要從用戶輸入或者外部數(shù)據(jù)源中獲取字符串形式的數(shù)字,并將其轉(zhuǎn)換為整數(shù)進(jìn)行計(jì)算和處理,在Java中,有幾種方法可以實(shí)現(xiàn)這種轉(zhuǎn)換,下面我將逐一介紹這些方法,需要的朋友可以參考下
    2025-06-06
  • Java?I/O流使用示例詳解

    Java?I/O流使用示例詳解

    Java.io?包幾乎包含了所有操作輸入、輸出需要的類。所有這些流類代表了輸入源和輸出目標(biāo)。本文將通過示例為大家詳細(xì)講講?I/O流的使用教程,需要的可以參考一下
    2022-08-08
  • 使用idea解決maven依賴沖突的問題

    使用idea解決maven依賴沖突的問題

    這篇文章主要介紹了使用idea解決maven依賴沖突,本文給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2020-12-12
  • SpringBoot幾種常用的接口日期格式化方法

    SpringBoot幾種常用的接口日期格式化方法

    在 Springboot 應(yīng)用程序中,日期時(shí)間格式化處理是非常重要的一方面,本文將總結(jié)SpringBoot幾種常用的接口日期格式化方法,通過示例代碼介紹了非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下
    2024-11-11
  • 詳解UDP協(xié)議格式及在java中的使用

    詳解UDP協(xié)議格式及在java中的使用

    這篇文章主要介紹了UDP協(xié)議格式及在java中的使用,本文給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2021-02-02
  • Java自動(dòng)化測(cè)試中多數(shù)據(jù)源的切換(實(shí)例講解)

    Java自動(dòng)化測(cè)試中多數(shù)據(jù)源的切換(實(shí)例講解)

    下面小編就為大家?guī)硪黄狫ava自動(dòng)化測(cè)試中多數(shù)據(jù)源的切換(實(shí)例講解)。小編覺得挺不錯(cuò)的,現(xiàn)在就分享給大家,也給大家做個(gè)參考。一起跟隨小編過來看看吧
    2017-10-10
  • Spring 框架需要的 jar 包解析與使用小結(jié)

    Spring 框架需要的 jar 包解析與使用小結(jié)

    本文總結(jié)Spring4.x項(xiàng)目的核心jar包作用及最小依賴組合,涵蓋IoC容器、AOP、Web、數(shù)據(jù)訪問等模塊,建議使用Maven/Gradle管理依賴,避免手動(dòng)配置導(dǎo)致版本混亂,助力開發(fā)者高效維護(hù)Spring應(yīng)用,感興趣的朋友跟隨小編一起看看吧
    2025-09-09
  • Spring中自帶的@Schedule實(shí)現(xiàn)自動(dòng)任務(wù)的過程解析

    Spring中自帶的@Schedule實(shí)現(xiàn)自動(dòng)任務(wù)的過程解析

    這篇文章主要介紹了關(guān)于Spring中自帶的@Schedule實(shí)現(xiàn)自動(dòng)任務(wù),本文通過實(shí)例代碼給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2023-06-06
  • Java集合之整體結(jié)構(gòu)

    Java集合之整體結(jié)構(gòu)

    Java中集合類是Java編程中使用最頻繁、最方便的類。接下來通過本文給大家介紹Java集合之整體結(jié)構(gòu),一起看看吧
    2016-05-05

最新評(píng)論

南江县| 且末县| 弥渡县| 呼伦贝尔市| 曲阳县| 延寿县| 买车| 永年县| 乌审旗| 内丘县| 房产| 阳春市| 会同县| 阿坝| 湖口县| 澄城县| 永城市| 青海省| 将乐县| 鄂托克旗| 阜城县| 上犹县| 蒲城县| 白朗县| 万安县| 九龙县| 确山县| 柞水县| 梁平县| 新化县| 河池市| 彭山县| 寿光市| 滦南县| 英吉沙县| 旬邑县| 六盘水市| 册亨县| 钟山县| 崇礼县| 南漳县|