-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy path140.单词拆分-ii.py
140 lines (120 loc) · 3.09 KB
/
140.单词拆分-ii.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
#
# @lc app=leetcode.cn id=140 lang=python3
#
# [140] 单词拆分 II
#
# https://leetcode-cn.com/problems/word-break-ii/description/
#
# algorithms
# Hard (37.02%)
# Likes: 124
# Dislikes: 0
# Total Accepted: 12K
# Total Submissions: 31.8K
# Testcase Example: '"catsanddog"\n["cat","cats","and","sand","dog"]'
#
# 给定一个非空字符串 s 和一个包含非空单词列表的字典
# wordDict,在字符串中增加空格来构建一个句子,使得句子中所有的单词都在词典中。返回所有这些可能的句子。
#
# 说明:
#
#
# 分隔时可以重复使用字典中的单词。
# 你可以假设字典中没有重复的单词。
#
#
# 示例 1:
#
# 输入:
# s = "catsanddog"
# wordDict = ["cat", "cats", "and", "sand", "dog"]
# 输出:
# [
# "cats and dog",
# "cat sand dog"
# ]
#
#
# 示例 2:
#
# 输入:
# s = "pineapplepenapple"
# wordDict = ["apple", "pen", "applepen", "pine", "pineapple"]
# 输出:
# [
# "pine apple pen apple",
# "pineapple pen apple",
# "pine applepen apple"
# ]
# 解释: 注意你可以重复使用字典中的单词。
#
#
# 示例 3:
#
# 输入:
# s = "catsandog"
# wordDict = ["cats", "dog", "sand", "and", "cat"]
# 输出:
# []
#
#
#
from typing import List
# @lc code=start
class Solution:
def wordBreak_1(self, s: str, wordDict: List[str]) -> List[str]:
"""
回溯
FIXME: 超时
"""
ans = []
wordSet = set(wordDict)
def backtrack(s, res):
if not s:
ans.append(' '.join(res))
return
for i in range(len(s)):
if s[:i + 1] in wordSet:
backtrack(s[i + 1:], res + [s[:i + 1]])
backtrack(s, [])
return ans
def wordBreak(self, s: str, wordDict: List[str]) -> List[str]:
"""
动态规划 + 回溯:
- dp[i] 表示 s[i:] 是否可拆分
"""
n = len(s)
wordSet = set(wordDict)
dp = [False] * (n + 1)
dp[-1] = True
for i in range(n - 1, -1, -1):
for j in range(i, n):
if s[i:j + 1] in wordSet and dp[j + 1]:
dp[i] = True
ans = []
def backtrack(s, i, res):
if i == n:
ans.append(' '.join(res))
return
for j in range(i, len(s)):
if s[i:j + 1] in wordSet and dp[j + 1]: # 当剩余部分可拆分时,才进行回溯,避免不必要的分支
backtrack(s, j + 1, res + [s[i:j + 1]])
backtrack(s, 0, [])
return ans
# @lc code=end
s = "pineapplepenapple"
wordDict = ["apple", "pen", "applepen", "pine", "pineapple"]
print(Solution().wordBreak(s, wordDict))
def wordBreak(s: str, wordDict: List[str]) -> List[str]:
ans = []
wordSet = set(wordDict)
def backtrack(s, i, res):
if i == len(s):
ans.append(' '.join(res))
return
for j in range(i, len(s)):
if s[i:j + 1] in wordSet:
backtrack(s, j + 1, res + [s[i:j + 1]])
backtrack(s, 0, [])
return ans
# print(wordBreak(s, wordDict))