演算法題之字串匹配問題

2021-10-01 19:17:26 字數 2573 閱讀 5960

我最近複習一道困難程度的演算法題,發現了許多有趣之處。在借鑑了他人解法後,發現從最簡單的情況反推到原題是一種解鎖新高端的感覺。從遞迴到動態規劃,思維上一步一步遞進,如同一部跌宕起伏的**,記錄下來和諸君共賞之。

題目如下:

給你乙個字串 s 和乙個字元規律 p,請你來實現乙個支援 '.' 和 '*' 的正規表示式匹配。

'.' 匹配任意單個字元

'*' 匹配零個或多個前面的那乙個元素

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

說明:s 可能為空,且只包含從 a-z 的小寫字母。

p 可能為空,且只包含從 a-z 的小寫字母,以及字元 . 和 *。

示例 1:

輸入:s = "aa"

p = "a"

輸出: false

解釋: "a" 無法匹配 "aa" 整個字串。

示例 2:

輸入:s = "aa"

p = "a*"

輸出: true

解釋: 因為 '*' 代表可以匹配零個或多個前面的那乙個元素, 在這裡前面的元素就是 'a'。因此,字串 "aa" 可被視為 'a' 重複了一次。

示例 3:

輸入:s = "ab"

p = ".*"

輸出: true

解釋: ".*" 表示可匹配零個或多個('*')任意字元('.')。

示例 4:

輸入:s = "aab"

p = "c*a*b"

輸出: true

解釋: 因為 '*' 表示零個或多個,這裡 'c' 為 0 個, 'a' 被重複一次。因此可以匹配字串 "aab"。

示例 5:

輸入:s = "mississippi"

p = "mis*is*p*."

輸出: false

這是一道關於字串匹配的問題,其中匹配字串裡面可能含有兩種特殊符號「.」和「*」。

說時候剛拿到這道題的時候我很懵逼,直接動手分析到帶有「*」符號的時候,感覺不同情況挺難分析下去的,甚至陷入了思維的僵局。

如果能讓問題簡化一下該多好呀,沒錯,如果我們把問題變成我們以前做過的問題或者容易做的問題,是否能從中發現新的思路?

假設問題變成:求兩個純字串進行匹配。實現**可以如下:

package main

func ismatch(text string, pattern string) bool else

}first_match := false

if pattern[0] == text[0]

return first_match && ismatch(text[1:], pattern[1:])

}func main()

這裡用到了遞迴,之所以這麼處理,是為了後續迭代。

那麼如果再增加乙個條件,把「.」符號加上,如果是帶有「.」符號的字串去匹配一段字串呢?

需要在實現的時候考慮第乙個位元組是否是該特殊符號

func ismatch2(text string, pattern string) bool  else 

}first_match := false

if pattern[0] == text[0] || pattern[0] == '.'

return first_match && ismatch2(text[1:], pattern[1:])

}

能解決「.」符號的情況,針對「*」符號的情況,我們可以進一步思考。

可能性:

func ismatch(text string, pattern string) bool  else 

}first_match := false

text_bool := false

if text != ""

if text_bool && (pattern[0] == text[0] || pattern[0] == '.')

if len(pattern) >=2 && pattern[1] == '*' else

}

這段**都是用遞迴實現的,但是遞迴的時間複雜度消耗更大,完全可以考慮將每一次遞迴的結果儲存下來,於是我們又可以往動態規劃的方向思考。

選擇dp儲存結果,dp[i][j]表示前i個字串被j個位元組pattern匹配的結果。

func ismatch(s string, p string) bool 

func dp(i int, j int, memory map[string]bool, s string, p string) bool

if j == len(p)

first := (i < len(s)) && (p[j] == s[i] || p[j] == '.')

var ans bool

if j <= (len(p) -2) && p[j+1] == '*' else

memory[keystr] = ans

return ans

}

反思:還有無更好的解法呢?比如把迴圈放到外層,而不是封裝成dp函式?

演算法之 字串匹配演算法

一說到兩個字串匹配,我們很自然就會想到用兩層迴圈來匹配,用這種方式就可以實現乙個字串是否包含另乙個字串了,這種演算法我們稱為 bf演算法。bf演算法,即暴力 brute force 演算法,是普通的模式匹配演算法,bf演算法的思想就是將目標串 s 的第乙個字元與模式串 t 的第乙個字元進行匹配,若相...

字串匹配問題 KMP匹配演算法

基本思想 字串匹配問題 在文字串中尋找是否有與模式串相同的子串 在字串匹配時,暴力匹配忽略了如果模式串開頭與中間有重複部分,在將模式串的後面的重複部分匹配後,無法繼續匹配的話,此時將模式串開頭實際上也已經被匹配了,可以直接從開頭重複部分之後開始匹配 這裡引入了乙個部分匹配值表,每個與模式串的字元對應...

演算法題之字串相乘問題

問題描述 題解 實現 public string multiply string num1,string num2 定義進製位 初始化為0 初始化到for迴圈中 int flag 0 獲取當前乘數num1和被乘數每一位的乘積結果,儲存在sub字串中 for int i mul1.length 1 i...