Location via proxy:   [ UP ]  
[Report a bug]   [Manage cookies]                
Skip to content

Commit ce18884

Browse files
committed
Word break - Leetcode problem.
1 parent 418ae72 commit ce18884

File tree

1 file changed

+107
-0
lines changed

1 file changed

+107
-0
lines changed

DynamicProgramming/wordBreak.py

Lines changed: 107 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,107 @@
1+
"""
2+
Task:
3+
Given a string and a list of words, return true if the string can be
4+
segmented into a space-separated sequence of one or more words.
5+
6+
Note that the same word may be reused
7+
multiple times in the segmentation.
8+
9+
Implementation notes: Trie + Dynamic programming up -> down.
10+
The Trie will be used to store the words. It will be useful for scanning
11+
available words for the current position in the string.
12+
13+
Leetcode:
14+
https://leetcode.com/problems/word-break/description/
15+
16+
Runtime: O(n * n)
17+
Space: O(n)
18+
"""
19+
20+
import functools
21+
from typing import Any
22+
23+
24+
def word_break(string: str, words: list[str]) -> bool:
25+
"""
26+
Return True if numbers have opposite signs False otherwise.
27+
28+
>>> word_break("applepenapple", ["apple","pen"])
29+
True
30+
>>> word_break("catsandog", ["cats","dog","sand","and","cat"])
31+
False
32+
>>> word_break("cars", ["car","ca","rs"])
33+
True
34+
>>> word_break('abc', [])
35+
False
36+
>>> word_break(123, ['a'])
37+
Traceback (most recent call last):
38+
...
39+
ValueError: the string should be not empty string
40+
>>> word_break('', ['a'])
41+
Traceback (most recent call last):
42+
...
43+
ValueError: the string should be not empty string
44+
>>> word_break('abc', [123])
45+
Traceback (most recent call last):
46+
...
47+
ValueError: the words should be a list of non-empty strings
48+
>>> word_break('abc', [''])
49+
Traceback (most recent call last):
50+
...
51+
ValueError: the words should be a list of non-empty strings
52+
"""
53+
54+
# Validation
55+
if not isinstance(string, str) or len(string) == 0:
56+
raise ValueError("the string should be not empty string")
57+
58+
if not isinstance(words, list) or not all(
59+
isinstance(item, str) and len(item) > 0 for item in words
60+
):
61+
raise ValueError("the words should be a list of non-empty strings")
62+
63+
64+
# Build trie
65+
trie: dict[str, Any] = {}
66+
word_keeper_key = "WORD_KEEPER"
67+
68+
for word in words:
69+
trie_node = trie
70+
for c in word:
71+
if c not in trie_node:
72+
trie_node[c] = {}
73+
74+
trie_node = trie_node[c]
75+
76+
trie_node[word_keeper_key] = True
77+
78+
len_string = len(string)
79+
80+
# Dynamic programming method
81+
@functools.cache
82+
def is_breakable(index: int) -> bool:
83+
"""
84+
>>> string = 'a'
85+
>>> is_breakable(1)
86+
True
87+
"""
88+
if index == len_string:
89+
return True
90+
91+
trie_node = trie
92+
for i in range(index, len_string):
93+
trie_node = trie_node.get(string[i], None)
94+
95+
if trie_node is None:
96+
return False
97+
98+
if trie_node.get(word_keeper_key, False) and is_breakable(i + 1):
99+
return True
100+
101+
return False
102+
103+
return is_breakable(0)
104+
105+
106+
if __name__ == "__main__":
107+
print(word_break("applepenapple", ["apple", "pen"]))

0 commit comments

Comments
 (0)