LeetCode-正則表達式匹配-Java

這題是《劍指Offer》的原題,在LeetCode上屬于hard難度尊惰,雖然面試可能不會考到這種題目,但能夠很好地訓練自己的思維~

書中的解法是遞歸白华,但因為沒有剪掉重復問題的結果蓉冈,導致時間開銷巨大方妖,LeetCode上測試大概3秒匣缘,相比之下窘哈,動態(tài)規(guī)劃只用了3ms澄成,這也足以看出動態(tài)規(guī)劃的剪枝對減少運行時間的作用是巨大的滑黔。

首先分析這道題為什么是動態(tài)規(guī)劃:例如,s = "abc" p = "abc"环揽,我們會從前向后逐個檢查s和p中對應的位置是不是相等略荡,如果相等就檢查下一個位置,所以大問題的結果可以看成去掉結尾字符的子串是否匹配和結尾是否匹配的組合歉胶,因此汛兜,這是個動態(tài)規(guī)劃問題。

既然是動態(tài)規(guī)劃問題通今,那就要確定狀態(tài)粥谬,因為*的存在,s和p能夠在長度不相等的情況下匹配辫塌,所以漏策,要用一個二維數(shù)組記錄狀態(tài):dp[i][j]表示s的前i個字符能否匹配上p的前j個。

選定狀態(tài)后臼氨,要先確定最小子問題的結果掺喻,也就是初值,有了初值储矩,才能自下向上逐步計算更大子問題的結果感耙。初值有以下三種情況:

  1. dp[0][0] = true,s和p的前0個元素一定是可以匹配的持隧,畢竟兩個空集相等嘛~
  2. dp[0][j]:比如即硼,s為空,p = "a*" 時能匹配屡拨,即dp[0][2] == true只酥,這是因為p[1] == '*',一個星號讓它前面的字符消失呀狼,同時dp[0][0] == true裂允,所以dp[0][2] == true。進行邏輯抽象后表述:只有當dp[0][j-2] == truep[j-1] == '*' 時赠潦,dp[0][j] = true;
  3. dp[i][0]:s不為空叫胖,p為空,這種情況無論如何都不能匹配她奥,所以全是false瓮增。
int row = s.length();
        int col = p.length();
        boolean[][] dp = new boolean[row+1][col+1];
        dp[0][0] = true;
        for(int j = 1; j <= col; j++){
            if(p.charAt(j-1) == '*' && j >= 2 && dp[0][j-2]){
                dp[0][j] = true;
            }
        }

接下來就到了最難的狀態(tài)轉(zhuǎn)移方程環(huán)節(jié),由于*的存在會讓問題變得復雜哩俭,我們按照p[j-1]是否為*來分類討論:

  1. p[j-1] != '*'
    1.1 p[j-1] == s[i-1]绷跑,兩個字符串的最后一位相等,則結果要由前面的子串判斷凡资,即:dp[i][j] = dp[i-1][j-1]砸捏;
    1.2 p[j-1] == '.',因為.可以匹配任一字符隙赁,和情況1.1是等價的垦藏,因此,結果依然是dp[i][j] = dp[i-1][j-1]伞访;
    1.3 p[j-1] 掂骏!= s[i-1],直接讓dp[i][j] = false厚掷,不解釋~
  2. p[j-1] == '*'
    2.1 p[j-2] == s[i-1] || p[j-2] == '.'弟灼,即*號前的字符和s[i-1]相等(.也可以認為是相等),還要再分為三種情況討論冒黑,以下三種情況只要有一個符合就可以:
    2.1.1 *不匹配字符:s = "ab" p = "abb*"田绑,s的前兩位已經(jīng)和p的前兩位匹配了,*只需要讓前面的字符消失即可抡爹,即dp[i][j] = dp[i][j-2]掩驱;
    2.1.2 *匹配1個字符:s = "aab" p = "aab*",此時的b*需要轉(zhuǎn)換成b冬竟,因此昙篙,dp[i][j] = dp[i][j-1]
    2.1.3 *匹配多個字符:s = "aabb" p = "aab*"诱咏,這時的b*需要轉(zhuǎn)換成bb苔可,也相當于在s末尾去掉一個b,即dp[i][j] = dp[i-1][j]袋狞;
    2.2 p[j-2] != s[i-1]焚辅,也就是s = "a" p = "b*"這種情況,只能去掉b*苟鸯,因此同蜻,dp[i][j] = dp[i][j-2]

最終的代碼:

class Solution {
    public boolean isMatch(String s, String p) {
        if(s == null || p == null) return false;
        int row = s.length();
        int col = p.length();
        boolean[][] dp = new boolean[row+1][col+1];
        //狀態(tài)矩陣初始化
        dp[0][0] = true;
        for(int j = 1; j <= col; j++){
            if(p.charAt(j-1) == '*' && j >= 2 && dp[0][j-2]){
                dp[0][j] = true;
            }
        }
        for(int i = 1; i <= row; i++){
            for(int j = 1; j <= col; j++){
                //p[j-1] != '*'的情況
                if(p.charAt(j-1) != '*'){
                    if(p.charAt(j-1) == s.charAt(i-1) || p.charAt(j-1) == '.'){
                        dp[i][j] = dp[i-1][j-1];
                    }
                //p[j-1] == '*'的情況
                }else{
                    //以下的情況都有j-2
                    if(j >= 2){
                        if(p.charAt(j-2) == s.charAt(i-1) || p.charAt(j-2) == '.'){
                            dp[i][j] = dp[i][j-2] || dp[i][j-1] || dp[i-1][j];
                        }else{
                            dp[i][j] = dp[i][j-2];
                        }
                    }
                }
            }
        }
        return dp[row][col];
    }
}

最終結果:


最后編輯于
?著作權歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末早处,一起剝皮案震驚了整個濱河市湾蔓,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌砌梆,老刑警劉巖默责,帶你破解...
    沈念sama閱讀 206,482評論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件贬循,死亡現(xiàn)場離奇詭異,居然都是意外死亡桃序,警方通過查閱死者的電腦和手機杖虾,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,377評論 2 382
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來媒熊,“玉大人奇适,你說我怎么就攤上這事÷ⅲ” “怎么了嚷往?”我有些...
    開封第一講書人閱讀 152,762評論 0 342
  • 文/不壞的土叔 我叫張陵,是天一觀的道長柠衅。 經(jīng)常有香客問我皮仁,道長,這世上最難降的妖魔是什么茄茁? 我笑而不...
    開封第一講書人閱讀 55,273評論 1 279
  • 正文 為了忘掉前任魂贬,我火速辦了婚禮,結果婚禮上裙顽,老公的妹妹穿的比我還像新娘付燥。我一直安慰自己,他們只是感情好愈犹,可當我...
    茶點故事閱讀 64,289評論 5 373
  • 文/花漫 我一把揭開白布键科。 她就那樣靜靜地躺著,像睡著了一般漩怎。 火紅的嫁衣襯著肌膚如雪勋颖。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 49,046評論 1 285
  • 那天勋锤,我揣著相機與錄音饭玲,去河邊找鬼。 笑死叁执,一個胖子當著我的面吹牛茄厘,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播谈宛,決...
    沈念sama閱讀 38,351評論 3 400
  • 文/蒼蘭香墨 我猛地睜開眼次哈,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了吆录?” 一聲冷哼從身側響起窑滞,我...
    開封第一講書人閱讀 36,988評論 0 259
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后哀卫,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體巨坊,經(jīng)...
    沈念sama閱讀 43,476評論 1 300
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 35,948評論 2 324
  • 正文 我和宋清朗相戀三年聊训,在試婚紗的時候發(fā)現(xiàn)自己被綠了抱究。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片恢氯。...
    茶點故事閱讀 38,064評論 1 333
  • 序言:一個原本活蹦亂跳的男人離奇死亡带斑,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出勋拟,到底是詐尸還是另有隱情勋磕,我是刑警寧澤,帶...
    沈念sama閱讀 33,712評論 4 323
  • 正文 年R本政府宣布敢靡,位于F島的核電站挂滓,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏啸胧。R本人自食惡果不足惜赶站,卻給世界環(huán)境...
    茶點故事閱讀 39,261評論 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望纺念。 院中可真熱鬧贝椿,春花似錦、人聲如沸陷谱。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,264評論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽烟逊。三九已至渣窜,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間宪躯,已是汗流浹背乔宿。 一陣腳步聲響...
    開封第一講書人閱讀 31,486評論 1 262
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留访雪,地道東北人详瑞。 一個月前我還...
    沈念sama閱讀 45,511評論 2 354
  • 正文 我出身青樓,卻偏偏與公主長得像冬阳,于是被迫代替她去往敵國和親蛤虐。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 42,802評論 2 345

推薦閱讀更多精彩內(nèi)容

  • 在C語言中,五種基本數(shù)據(jù)類型存儲空間長度的排列順序是: A)char B)char=int<=float C)ch...
    夏天再來閱讀 3,325評論 0 2
  • 引子 思路:看到兩個序列去匹配的問題肝陪,最自然的想法是雙層循環(huán)嘗試對齊匹配驳庭,我們假設表格數(shù)字為1代表匹配成功,0代表...
    閆品品閱讀 1,103評論 1 1
  • 題目 (困難)給定一個字符串 (s) 和一個字符模式 (p)。實現(xiàn)支持 '.' 和 '*' 的正則表達式匹配饲常。 '...
    玖月晴閱讀 796評論 0 0
  • 字符串匹配KMP算法詳解 1. 引言 以前看過很多次KMP算法蹲堂,一直覺得很有用,但都沒有搞明白贝淤,一方面是網(wǎng)上很少有...
    張晨輝Allen閱讀 2,385評論 0 3
  • 我的襪子不見了柒竞,今早我的一只襪子不見了。本來是圓滿的一雙播聪,現(xiàn)在只剩一只了朽基,很奇怪,為什么會不見了呢离陶?我找遍了所有可...
    不貳郭閱讀 135評論 0 0