-
Notifications
You must be signed in to change notification settings - Fork 1.6k
/
construct-string-with-minimum-cost-easy.py
125 lines (109 loc) · 3.55 KB
/
construct-string-with-minimum-cost-easy.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
# Time: O(n * w * l)
# Space: O(l)
import itertools
# dp
class Solution(object):
def minimumCost(self, target, words, costs):
"""
:type target: str
:type words: List[str]
:type costs: List[int]
:rtype: int
"""
INF = float("inf")
l = max(len(w) for w in words)
dp = [INF]*(l+1)
dp[0] = 0
for i in xrange(len(target)):
if dp[i%len(dp)] == INF:
continue
for w, c in itertools.izip(words, costs):
if target[i:i+len(w)] == w:
dp[(i+len(w))%len(dp)] = min(dp[(i+len(w))%len(dp)], dp[i%len(dp)]+c)
dp[i%len(dp)] = INF
return dp[len(target)%len(dp)] if dp[len(target)%len(dp)] != INF else -1
# Time: O(n^2 + w * l)
# Space: O(t)
import itertools
# trie, dp
class Solution2(object):
def minimumCost(self, target, words, costs):
"""
:type target: str
:type words: List[str]
:type costs: List[int]
:rtype: int
"""
INF = float("inf")
def query(i):
curr = trie
for j in xrange(i, len(target)):
x = target[j]
if x not in curr:
break
curr = curr[x]
if "_end" in curr:
dp[j+1] = min(dp[j+1], dp[i]+curr["_end"])
_trie = lambda: collections.defaultdict(_trie)
trie = _trie()
for w, c in itertools.izip(words, costs):
node = reduce(dict.__getitem__, w, trie)
if "_end" not in node:
node["_end"] = INF
node["_end"] = min(node["_end"], c)
dp = [INF]*(len(target)+1)
dp[0] = 0
for i in xrange(len(target)):
if dp[i] == INF:
continue
query(i)
return dp[-1] if dp[-1] != INF else -1
# Time: O(n^2 + w * l)
# Space: O(t)
import itertools
# trie, dp
class Solution3(object):
def minimumCost(self, target, words, costs):
"""
:type target: str
:type words: List[str]
:type costs: List[int]
:rtype: int
"""
INF = float("inf")
class Trie(object):
def __init__(self):
self.__nodes = []
self.__mns = []
self.__new_node()
def __new_node(self):
self.__nodes.append([-1]*26)
self.__mns.append(INF)
return len(self.__nodes)-1
def add(self, w, c):
curr = 0
for x in w:
x = ord(x)-ord('a')
if self.__nodes[curr][x] == -1:
self.__nodes[curr][x] = self.__new_node()
curr = self.__nodes[curr][x]
self.__mns[curr] = min(self.__mns[curr], c)
def query(self, i):
curr = 0
for j in xrange(i, len(target)):
x = ord(target[j])-ord('a')
if self.__nodes[curr][x] == -1:
break
curr = self.__nodes[curr][x]
if self.__mns[curr] != INF:
dp[j+1] = min(dp[j+1], dp[i]+self.__mns[curr])
trie = Trie()
for w, c in itertools.izip(words, costs):
trie.add(w, c)
dp = [INF]*(len(target)+1)
dp[0] = 0
for i in xrange(len(target)):
if dp[i] == INF:
continue
trie.query(i)
return dp[-1] if dp[-1] != INF else -1