美文网首页
LintCode 582. 单词拆分II

LintCode 582. 单词拆分II

作者: CW不要无聊的风格 | 来源:发表于2020-07-02 12:40 被阅读0次

题目描述

给一字串s和单词的字典dict,在字串中增加空格来构建一个句子,并且所有单词都来自字典。

返回所有有可能的句子。



测试样例

输入:"lintcode",["de","ding","co","code","lint"]

输出:["lint code", "lint co de"]

解释:

插入一个空格是"lint code",插入两个空格是 "lint co de"

输入:"a",[]

输出:[]

解释:字典为空


解题思路

1、DFS

自然而然容易想到用深搜来解决,而且代码也很精炼,整个dfs不到10行就可以搞定。

具体做法是每次深搜都取一定长度的前缀字符串,若其在词典中,则对后面的子串进行进一步的深搜;深搜的终止条件是当前字符串为空,则将目前为止获得的分词组合加入到最终结果。

整体思路是这样没错,但是如果仅仅是这样的话你会发现它会超时过不了,超时的是以下测试样例:

"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaabaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"

["a","aa","aaa","aaaa","aaaaa","aaaaaa","aaaaaaa","aaaaaaaa","aaaaaaaaa","aaaaaaaaaa"]

观察了下,发现字符串中的字母'b'在词典中每个词中都没有出现,于是在进行dfs前先对字符串和词典中所有的字母进行判断,若字符串中的所有字母不是词典中所有字母的子集,那么说明这是不可能分词成功的,直接返回空列表即可。加上这个条件,这种naive dfs的方案就能过了。

2、记忆化搜索I

其实整体思路和过程都和dfs差不多,只不过额外使用了一个dict来记录当前字符串与其子串所组合的分词结果,这样遇到重复的字符串时,就可以直接返回记录的结果而无需重复操作。需要注意的一点时,每次搜索时若当前字符串在词典中,则直接将其加入到分词组合的list中。

3、记忆化搜索II

记忆化搜索的另一种形式,上述的1、2都是从输入字符串的每个位置下手取前缀,而该方式是从词典中的每个词出发,若其是当前字符串的前缀,则将其和后缀子串返回的结果进行组合。同样地,如果该词与当前字符串完全一致,则直接将其加入分词组合的list中。


代码

1、DFS

class Solution:

    """

    @param: s: A string

    @param: wordDict: A set of words.

    @return: All possible sentences.

    """

    def wordBreak(self, s, wordDict):

        if not wordDict:

            return []

        s1 = set(s)

        s2 = set(''.join(wordDict))

        if not s1.issubset(s2):

            return []

        result = []

        self.dfs(s, wordDict, [], result)

        return result

    def dfs(self, s, wordDict, tmp, result):

        if not s:

            result.append(' '.join(tmp))

            return

        for i in range(1, len(s) + 1):

            if s[:i] in wordDict:

                self.dfs(s[i:], wordDict, tmp + [s[:i]], result)

2、 记忆化搜索I

class Solution:

    """

    @param: s: A string

    @param: wordDict: A set of words.

    @return: All possible sentences.

    """

    def wordBreak(self, s, wordDict):

        if not wordDict:

            return []

        return self.dfs(s, wordDict, {})

    def dfs(self, s, wordDict, memo):

        """记忆化搜索"""

        if s in memo:

            return memo[s]

        if not s:

            return []

        partitions = []

        for i in range(1, len(s)):

            if s[:i] in wordDict:

                for sub_partition in self.dfs(s[i:], wordDict, memo):

                    # 当前前缀与后面子字符串的各个分割结果组合

                    partitions.append('{} {}'.format(s[:i], sub_partition))

        # 若当前整个字符串在词典中,要加入结果中

        if s in wordDict:

            partitions.append(s)

        # 存储记忆

        memo[s] = partitions

        return partitions

3、记忆化搜索II

classSolution:

     """

    @param: s: A string

    @param: wordDict: A set of words.

    @return: All possible sentences.

    """   

    defwordBreak(self, s, wordDict):        if not wordDict:

            return []

        return self.dfs(s, wordDict, {})

    defdfs(self, s, wordDict, memo):       

        """记忆化搜索"""       

        if s in memo:

            return memo[s]

        if not s:

            return []

        partitions = []

        for word in wordDict:

            # 词典中的词必须是当前字符串的前缀            # 另外,注意需要判断word是""的情况!           

            if not (s.startswith(word) and word):

                continue           

            if word == s:

                partitions.append(word)

            else:

                for sub_partition in self.dfs(s[len(word):], wordDict, memo):

                    partitions.append('{} {}'.format(word, sub_partition))

        # 存储记忆        memo[s] = partitions

        return partitions

相关文章

网友评论

      本文标题:LintCode 582. 单词拆分II

      本文链接:https://www.haomeiwen.com/subject/ruolqktx.html