單字接龍 用單字拼出整個句子 DP應用 Leetcode #140_Word Break II

小松鼠
發佈於演算法專欄 個房間
閱讀時間約 8 分鐘

題目敘述

題目會給定我們一個字串s,和一組單字庫wordDict。

問我們能不能透過字串串接的方式,從單字庫裡面的字拼成原本的字串s?

可以的話,返回所有拼字接龍的解答

無解的話,返回空陣列 [ ]。

註:

題目還允許重複使用字庫裡面的字去串接


題目的原文敘述


測試範例

Example 1:

Input: s = "catsanddog", wordDict = ["cat","cats","and","sand","dog"]
Output: ["cats and dog","cat sand dog"]

Example 2:

Input: s = "pineapplepenapple", wordDict = ["apple","pen","applepen","pine","pineapple"]
Output: ["pine apple pen apple","pineapple pen apple","pine applepen apple"]
Explanation: Note that you are allowed to reuse a dictionary word.

Example 3:

Input: s = "catsandog", wordDict = ["cats","dog","sand","and","cat"]
Output: []

約束條件

Constraints:

  • 1 <= s.length <= 20

目標字串s長度介於1~20之間。

  • 1 <= wordDict.length <= 1000

單字庫最少有一個單字,最多有1000個單字。

  • 1 <= wordDict[i].length <= 10

每個單字長度最少一個字,最長10個字

  • s and wordDict[i] consist of only lowercase English letters.

題目輸入全程都只會用到小寫英文字母。

  • All the strings of wordDict are unique.

單字庫裡的單字都是相異,保證不重複。

  • Input is generated in a way that the length of the answer doesn't exceed 105.

測試平台保證解答長度不會超過十萬。


觀察: 如何用單字串接?

其實這題是系列題前一題Word Break I 的延伸。

一魚n吃 用DP來進行字串拆分配對 Word Break_Leetcode #139


raw-image



原本在前一題Word Break I問的是,能不能拼接成功? 是回答Yes / No的是非題

這題Word Break II類似,改成問如何拼接,請把拼接的方法全部列出來的應用題



演算法 DP動態規劃 + 針對單字長度做最佳化


怎麼定義DP狀態?

可以定義DP[i] 代表子字串s[i:]的單字串接方法。

那麼最終答案自然就是DP[0],也就是s[0:] = s本身的單字串接方法。


DP遞迴關係(狀態轉移關係式)是怎麼表達?

逐步推進,假如我們找到某個prefix前綴剛好是單字庫裡的某個單字,那麼prefix加上剩下的後綴子字串串接方法就是合法的拼接方法數。

DP[i] += DP[i+length] 如果 s[i: i+length]這個前綴剛好是單字庫裡的單字。


優化的技巧

推進的時候,可以不用暴力的去try每個index,只要針對有可能的長度去做搜尋即可

為什麼?

為因單字庫已經事先知道了,那些長度不可能的前綴,是沒有辦法被單字串接的,可以直接跳過。


遞迴什麼時候結束?

當index前進到字串s的未端,也就是len(s)的時候,代表已經用單字串接出整個字串s。

這時候後面已經式空字串沒有東西了,遞迴結束,自然停止。


OK,到這邊DP狀態定義、DP狀態轉移關係式、終止條件都釐清了。

接下來轉成具體的程式碼即可。


程式碼 DP動態規劃 + 針對單字長度做最佳化


# DP = DFS + memoization = DFS + DP table

class Solution:
def wordBreak(self, s: str, wordDict: List[str]) -> List[str]:

# word set to speed up element membership lookup
wordBank = set(wordDict)

# set of length of words
possible_length = set( map(len,wordBank ) )

## DP table
# key: search index
# value: list of matched words in s[index:]
dp = { len(s): [ [] ]}

def match(index: int) -> List[List[str]]:

if index in dp:
return dp[index]

ans = list()

# Scan each possible split index from left to right
for length in possible_length:

# This round is skipped due to length out of boundary
if index+length > len(s):
continue

word = s[index:index+length]
if word in wordBank:
# Current word is matched
# Try to match remaining substring
parse_postfix = match(index+length)
for parsing_reulst in parse_postfix:
ans.append( [word] + parsing_reulst )

dp[index] = ans
return ans

# ------------------------------------------
return [" ".join(words) for words in match(index=0) ]

複雜度分析

令字串s的長度為n,

時間複雜度: O( n * 2^n )

最差情況下,單字庫裡的單字只有一個字母,相當於每個切割點都有展開來檢查,耗費O( 2^n )。

每次檢查需要耗費O(n)去切割前綴字串,看看是否在單字庫裡面。


空間複雜度: O( n * 2^n )

總共有O(2^n)種展開狀態

每個合法狀態最後寫入解答時,拼接總長度剛好為O(n)。


關鍵知識點

聯想到系列題的Word Break I,用到的都是同一種想法,

從左到右逐漸推進,檢查每個前綴是否能匹配單字庫裡的單字。
接著DP遞迴呼叫,檢查剩下的後綴子字串


Reference

[1] Word Break II - LeetCode

52會員
339內容數
由有業界實戰經驗的演算法工程師, 手把手教你建立解題的框架, 一步步寫出高效、清晰易懂的解題答案。 著重在讓讀者啟發思考、理解演算法,熟悉常見的演算法模板。 深入淺出地介紹題目背後所使用的演算法意義,融會貫通演算法與資料結構的應用。 在幾個經典的題目融入一道題目的多種解法,或者同一招解不同的題目,擴展廣度,並加深印象。
留言0
查看全部
發表第一個留言支持創作者!
你可能也想看
【一起走過的階段】《班親會後記/抽獎/21天感恩日記》《文/魔莉園長》《名單數字號碼請核對》到了班親會結束,這個學期就差不多接近尾聲了。 這個時候,去回顧這個階段,似乎會很清楚, 有些東西的經歷是必然的。 你必須得經過、才會知道那是什麼? 否則日子一樣過、孩子一樣在長大, 那不知不覺中,一晃眼而過的或許都是機會。 面對你無需太用力,與太用心,孩子一樣在長大的事實, 難免會
Thumbnail
avatar
【輕輕吹,蒲公英飛】《快樂的孩子,分享快樂》
2024-01-22
活動規劃產業 - 線上預約功能推薦:簡單易用,輕鬆客製 24 小時自動接單系統!SimplyBook.me 線上預約系統,提供超過 60 種彈性預約功能,讓不同的產業經營者,都能找到適合的功能並打造專屬線上預約系統。而本篇文章將會以「活動規劃產業」為切入,為您分享適合的客製功能,以及如何透過 SimplyBook.me 宣傳服務或產品,並透過詳細的報表來追蹤預約資訊。
Thumbnail
avatar
Haoyi Fan
2023-03-27
英文融入生活,讀書考試得心應手:八個增加英文接觸時間的提案(附多益單字卡)多益960分是堆疊而來的!只要有意將英文融入生活,終得甜美碩果!被動學習、主動學習雙管齊下:語言設定、賽事轉播、聲音串流、電影戲劇都是好幫手。附贈超過600字的單字卡祝你一臂之力!
Thumbnail
avatar
陳穩
2023-01-30
мрія (Ukrainian 語系單字) 與漢字「夢」或「夢想」的橋接Мрія (夢;夢想) 也是在 Ukraine (我們的家國;於界沿之地;於境緣之邑;由己聯邑。漢文或音譯為語音漢字「烏克蘭」) 製造的全球最大飛機 АН-225 (英譯 AN-225;漢文或譯「安-225」) 運輸機的名字。……
Thumbnail
avatar
羅聖爾
2022-03-01
Chiron (Dutch 語系單字) 與地名「秀朗」及「傷療」的橋接,兼談 Pattai完整標題:Chiron (Dutch 語系單字) 與地名「秀朗」可能的本義「傷療」的橋接,兼談 Pattai
Thumbnail
avatar
羅聖爾
2021-09-14
Seqalu (Paywan 語系英式拼音單字) 與「坐轎人聯;瑯嶠聯;恒春聯」等的橋接完整標題:Seqalu (Paywan 語系英式拼音單字) 與「坐轎人聯;瑯嶠聯;恒春聯;民人聯;己由國的人聯;飾頸以琉聯;擅咒的人聯」等的轉換密碼
Thumbnail
avatar
羅聖爾
2021-08-22
rinascerò (Italiano 語系單字) 與「再生將我;重生將我」等的橋接完整標題:rinascerò (Italiano 語系單字) 與漢字「再生將我」或「重生將我」即意通「我將再生」、「我會再生」或「我將重生」、「我會重生」等的轉換密碼
Thumbnail
avatar
羅聖爾
2021-07-18
【接種疫苗】必學英文單字大補帖,你不可不知的「疫情英文」知識!今天一次給你滿滿必學【接種疫苗英文單字】大補帖與相關知識,「群體免疫與社區免疫」英文單字怎麼說?「抗體、抗原」英文怎麼說?「體外試驗、動物試驗、體內試驗、臨床試驗」英文怎麼說?注射疫苗的效力、不良事件、不良反應的英文又怎麼說呢?學完這些單字後,你可以用英文談論疫苗,看看你的「英文抵抗力」如何!
Thumbnail
avatar
外帶英文
2021-06-24
Улаанбаатар хот (Mongolian 語系單字) 與漢字「紅雄英埠」的橋接Улаанбаатар (紅雄英) 一名帶有「紅」的意義,一般中文漢字則音譯為「烏蘭巴托」。但因爲漢字「烏」也有「黑」的意思,竟可能導致這個城市名稱看起來好像有由「紅」變「黑」的感覺呢!......是不是好歹也翻譯成「紅蘭巴托」比較妥當呢?......
Thumbnail
avatar
羅聖爾
2021-01-25