Skip to content

Commit 214124e

Browse files
committed
palindrome
1 parent 43cd3ee commit 214124e

File tree

1 file changed

+106
-70
lines changed

1 file changed

+106
-70
lines changed

132 Palindrome Partitioning II.py

Lines changed: 106 additions & 70 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,106 @@
77
Return 1 since the palindrome partitioning ["aa","b"] could be produced using 1 cut.
88
"""
99
__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+
11110
def minCut_MLE(self, s):
12111
"""
13112
bfs
@@ -79,7 +178,7 @@ def minCut_TLE(self, s):
79178
return dp[0][length]
80179

81180
def is_palindrome(self, s):
82-
return s==s[::-1]
181+
return s == s[::-1]
83182

84183
def minCut_TLE2(self, s):
85184
"""
@@ -123,7 +222,7 @@ def minCut_TLE2(self, s):
123222
for i in xrange(length, -1, -1):
124223
for j in xrange(i+2, length+1):
125224
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]
127226
except IndexError:
128227
dp2[i][j] = True
129228

@@ -147,70 +246,7 @@ def minCut_TLE2(self, s):
147246
return dp[0][length]
148247

149248

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

Comments
 (0)