动态规划

【DP】139. Word Break

2019-06-03  本文已影响0人  牛奶芝麻

问题描述:

Given a non-empty string s and a dictionary wordDict containing a list of non-empty words, determine if s can be segmented into a space-separated sequence of one or more dictionary words.

Note:

Example 1:
Input: s = "leetcode", wordDict = ["leet", "code"]
Output: true
Explanation: Return true because "leetcode" can be segmented as "leet code".
Example 2:
Input: s = "applepenapple", wordDict = ["apple", "pen"]
Output: true
Explanation: Return true because "applepenapple" can be segmented as "apple pen apple".
             Note that you are allowed to reuse a dictionary word.
Example 3:
Input: s = "catsandog", wordDict = ["cats", "dog", "sand", "and", "cat"]
Output: false

解题思路:

题目大意是:给定一个非空字符串 s 和一个包含非空单词列表的字典 wordDict,判定 s 是否可以被空格拆分为一个或多个在字典中出现的单词。

注意: 字典中有可能有多余的单词。

想法1(贪婪算法,错误做法):

当然,我们可以将 wordDict 转化为 dict 加速判断。实现代码如下:

class Solution:
    def wordBreak(self, s: str, wordDict: List[str]) -> bool:
        dic = dict()
        for word in wordDict:
            dic[word] = True
        cur, nex = 0, 1
        while nex != len(s):
            if s[cur:nex] in dic:
                cur = nex
            nex += 1
        if s[cur:nex] in dic:
            return True
        return False

但是,这样的想法是错误的!!! 我们使用这种贪心策略,会忽略这样的问题。

s = "aaaaaaa"
wordDict = ["aaaa","aaa"]

我们相当于每次取最短,上述代码最后的划分结果就是 ["aaa", "aaa", "a"],从而返回 False 的错误答案。

想法2(DP,正确做法):

举例说明:

s = "catsandog", wordDict = ["cats", "cat", "and", "og", "aaa"]

首先 dp[0] = True;在遍历的过程中,dp[3] = True 因为以 t 结尾的 cat 在字典里面,且 dp[3-3] 为 True(这就是 dp[0] 为 True 的作用);dp[4] = True 因为以 s 结尾的 cats 在字典里且 dp[4-4] 为 True;dp[7] 为 True 因为以 d 结尾的 and 在字典里且 dp[7-3] 为 True;dp[9] 为 True 因为以 g 结尾的 og 在字典里且 dp[9-2] 为 True;最后,dp[-1] = dp[9] = True,得到划分结果 ['cats', 'and', 'og']。

其实,可以发现 s[i] = True 将字符串划分为两部分,s[0:i] 为可以在字典中划分的,s[i:] 为待划分的字符串。

时间复杂度为 O(N*M),空间复杂度 O(N),其中 N 为字符串长度,M 为字典中 word 个数。

Python3 实现:

class Solution:
    def wordBreak(self, s: str, wordDict: List[str]) -> bool:
        dp = [True] + [False] * len(s)
        for i in range(1, len(s) + 1):
            for word in wordDict:
                if i >= len(word) and dp[i-len(word)] and word == s[i-len(word):i]:
                    dp[i] = True
        return dp[-1]
上一篇下一篇

猜你喜欢

热点阅读