7
7
Return 1 since the palindrome partitioning ["aa","b"] could be produced using 1 cut.
8
8
"""
9
9
__author__ = 'Danyang'
10
- class Solution :
10
+
11
+
12
+ class Solution (object ):
13
+ def minCut (self , s ):
14
+ """
15
+ Let P[i][j] indicates whether s[i:j] is palindrome
16
+ P[i][j] = P[i+1][j-1] && s[i] == s[j-1]
17
+
18
+ Left C[i] represents the min cut for s[:i]
19
+ C[i] = 0 if s[:i] is palindrome
20
+ C[i] = min(C[j]+1 for j<i if s[j:i] is palindrome)
21
+ """
22
+ n = len (s )
23
+
24
+ P = [[False for _ in xrange (n + 1 )] for _ in xrange (n + 1 )]
25
+ for i in xrange (n + 1 ): # len 0
26
+ P [i ][i ] = True
27
+ for i in xrange (n ): # len 1
28
+ P [i ][i + 1 ] = True
29
+
30
+ for i in xrange (n , - 1 , - 1 ): # len 2 and above
31
+ for j in xrange (i + 2 , n + 1 ):
32
+ P [i ][j ] = P [i + 1 ][j - 1 ] and s [i ] == s [j - 1 ]
33
+
34
+ C = [i for i in xrange (n + 1 )] # initial values, max is all cut
35
+ for i in xrange (n + 1 ):
36
+ if P [0 ][i ]:
37
+ C [i ] = 0
38
+ else :
39
+ C [i ] = min (
40
+ C [j ] + 1
41
+ for j in xrange (i )
42
+ if P [j ][i ]
43
+ )
44
+
45
+ return C [n ]
46
+
47
+ def minCut_dp (self , s ):
48
+ """
49
+ dp
50
+
51
+ a b a b b b a b b a b a
52
+ i k
53
+ if s[i:k+1] is palindrome, #cut is 0; otherwise
54
+ cut s[i:k+1] into palindrome, the #cut:
55
+ cut the s[i:k+1] to two parts
56
+ cut the left part into palindrome, #cut is dp[i, j]
57
+ cut the right part into palindrome, #cut is dp[j+1, k+1]
58
+ find the minimum for above
59
+
60
+ dp[i, n+1] = min(dp[i, j]+dp[j, k+1]+1)
61
+
62
+ when drawing the matrix, you will find it difficult to construct it at one shot (especially, vertical line)
63
+
64
+
65
+ To avoid TLE, use 1-d dp instead of 2-d dp
66
+ D[i] represents #cut for s[i:length+1]
67
+ if s[i:j] is palindrome and we need #cut for s[j:] is D[j], then
68
+ for minimum: D[i] = min(D[j+1]+1) for all j
69
+
70
+ To avoid TLE, use dp for determination of palindrome
71
+ Determine s[i:k+1] is palindrome:
72
+ P[i, k+1] = P[i+1, k] && s[i]==s[k]
73
+
74
+ * another algorithm is dfs with global_min
75
+ * to tell s[i:k+1] whether it is palindrome can be optimized by dp
76
+ :param s: str
77
+ :return: int
78
+ """
79
+ if not s :
80
+ return 0
81
+
82
+ length = len (s )
83
+ # palindrome dp
84
+ P = [[False for _ in xrange (length + 1 )] for _ in xrange (length + 1 )]
85
+ for i in xrange (length + 1 ):
86
+ try :
87
+ P [i ][i ] = True
88
+ P [i ][i + 1 ] = True
89
+ except IndexError :
90
+ pass
91
+
92
+ for i in xrange (length , - 1 , - 1 ):
93
+ for j in xrange (i + 2 , length + 1 ):
94
+ try :
95
+ P [i ][j ] = P [i + 1 ][j - 1 ] and s [i ] == s [j - 1 ]
96
+ except IndexError :
97
+ P [i ][j ] = True
98
+
99
+ # min cut dp
100
+ D = [length - i - 1 for i in xrange (length )] # max is all cut
101
+ for i in xrange (length - 1 , - 1 , - 1 ):
102
+ if P [i ][length ]:
103
+ D [i ] = 0
104
+ else :
105
+ for j in xrange (i + 1 , length ):
106
+ if P [i ][j ]:
107
+ D [i ] = min (D [i ], D [j ]+ 1 )
108
+ return D [0 ]
109
+
11
110
def minCut_MLE (self , s ):
12
111
"""
13
112
bfs
@@ -79,7 +178,7 @@ def minCut_TLE(self, s):
79
178
return dp [0 ][length ]
80
179
81
180
def is_palindrome (self , s ):
82
- return s == s [::- 1 ]
181
+ return s == s [::- 1 ]
83
182
84
183
def minCut_TLE2 (self , s ):
85
184
"""
@@ -123,7 +222,7 @@ def minCut_TLE2(self, s):
123
222
for i in xrange (length , - 1 , - 1 ):
124
223
for j in xrange (i + 2 , length + 1 ):
125
224
try :
126
- dp2 [i ][j ] = dp2 [i + 1 ][j - 1 ] and s [i ]== s [j - 1 ]
225
+ dp2 [i ][j ] = dp2 [i + 1 ][j - 1 ] and s [i ] == s [j - 1 ]
127
226
except IndexError :
128
227
dp2 [i ][j ] = True
129
228
@@ -147,70 +246,7 @@ def minCut_TLE2(self, s):
147
246
return dp [0 ][length ]
148
247
149
248
150
- def minCut (self , s ):
151
- """
152
- dp
153
-
154
- a b a b b b a b b a b a
155
- i k
156
- if s[i:k+1] is palindrome, #cut is 0; otherwise
157
- cut s[i:k+1] into palindrome, the #cut:
158
- cut the s[i:k+1] to two parts
159
- cut the left part into palindrome, #cut is dp[i, j]
160
- cut the right part into palindrome, #cut is dp[j+1, k+1]
161
- find the minimum for above
162
-
163
- dp[i, n+1] = min(dp[i, j]+dp[j, k+1]+1)
164
-
165
- when drawing the matrix, you will find it difficult to construct it at one shot (especially, vertical line)
166
-
167
-
168
- To avoid TLE, use 1-d dp instead of 2-d dp
169
- D[i] represents #cut for s[i:length+1]
170
- if s[i:j] is palindrome and we need #cut for s[j:] is D[j], then
171
- for minimum: D[i] = min(D[j+1]+1) for all j
172
-
173
- To avoid TLE, use dp for determination of palindrome
174
- Determine s[i:k+1] is palindrome:
175
- pan[i, k+1] = pan[i+1, k] && s[i]==s[k]
176
-
177
- * another algorithm is dfs with global_min
178
- * to tell s[i:k+1] whether it is palindrome can be optimized by dp
179
- :param s: str
180
- :return: int
181
- """
182
- if not s :
183
- return 0
184
-
185
- length = len (s )
186
- # palindrome dp
187
- pan = [[False for _ in xrange (length + 1 )] for _ in xrange (length + 1 )]
188
- for i in xrange (length + 1 ):
189
- try :
190
- pan [i ][i ] = True
191
- pan [i ][i + 1 ] = True
192
- except IndexError :
193
- pass
194
-
195
- for i in xrange (length , - 1 , - 1 ):
196
- for j in xrange (i + 2 , length + 1 ):
197
- try :
198
- pan [i ][j ] = pan [i + 1 ][j - 1 ] and s [i ]== s [j - 1 ]
199
- except IndexError :
200
- pan [i ][j ] = True
201
-
202
- # min cut dp
203
- D = [length - i - 1 for i in xrange (length )] # max is all cut
204
- for i in xrange (length - 1 , - 1 , - 1 ):
205
- if pan [i ][length ]:
206
- D [i ] = 0
207
- else :
208
- for j in xrange (i + 1 , length ):
209
- if pan [i ][j ]:
210
- D [i ] = min (D [i ], D [j ]+ 1 )
211
- return D [0 ]
212
-
213
-
214
-
215
- if __name__ == "__main__" :
216
- assert Solution ().minCut ("apjesgpsxoeiokmqmfgvjslcjukbqxpsobyhjpbgdfruqdkeiszrlmtwgfxyfostpqczidfljwfbbrflkgdvtytbgqalguewnhvvmcgxboycffopmtmhtfizxkmeftcucxpobxmelmjtuzigsxnncxpaibgpuijwhankxbplpyejxmrrjgeoevqozwdtgospohznkoyzocjlracchjqnggbfeebmuvbicbvmpuleywrpzwsihivnrwtxcukwplgtobhgxukwrdlszfaiqxwjvrgxnsveedxseeyeykarqnjrtlaliyudpacctzizcftjlunlgnfwcqqxcqikocqffsjyurzwysfjmswvhbrmshjuzsgpwyubtfbnwajuvrfhlccvfwhxfqthkcwhatktymgxostjlztwdxritygbrbibdgkezvzajizxasjnrcjwzdfvdnwwqeyumkamhzoqhnqjfzwzbixclcxqrtniznemxeahfozp" )== 452
249
+ if __name__ == "__main__" :
250
+ assert Solution ().minCut ("aabbc" ) == 2
251
+ assert Solution ().minCut (
252
+ "apjesgpsxoeiokmqmfgvjslcjukbqxpsobyhjpbgdfruqdkeiszrlmtwgfxyfostpqczidfljwfbbrflkgdvtytbgqalguewnhvvmcgxboycffopmtmhtfizxkmeftcucxpobxmelmjtuzigsxnncxpaibgpuijwhankxbplpyejxmrrjgeoevqozwdtgospohznkoyzocjlracchjqnggbfeebmuvbicbvmpuleywrpzwsihivnrwtxcukwplgtobhgxukwrdlszfaiqxwjvrgxnsveedxseeyeykarqnjrtlaliyudpacctzizcftjlunlgnfwcqqxcqikocqffsjyurzwysfjmswvhbrmshjuzsgpwyubtfbnwajuvrfhlccvfwhxfqthkcwhatktymgxostjlztwdxritygbrbibdgkezvzajizxasjnrcjwzdfvdnwwqeyumkamhzoqhnqjfzwzbixclcxqrtniznemxeahfozp" ) == 452
0 commit comments