class Solution: # @param s, s string # @return an array def _buildPalindromeCache(self, s): transformed = "#" + "#".join(s) + "#" palindrome_len = [1] * len(transformed) center = 0 farest = 0 for index in xrange(1, len(transformed)): if farest <= index: tryingLen = 1 else: preComputedLen = palindrome_len[2*center-index] if preComputedLen + index > farest: tryingLen = farest + 1 - index else: palindrome_len[index] = preComputedLen continue while index + tryingLen < len(transformed) and \ index - tryingLen >= 0: if transformed[index + tryingLen] == \ transformed[index - tryingLen]: tryingLen += 1 else: break if index + tryingLen -1 > farest: farest = index + tryingLen -1 center = index palindrome_len[index] = tryingLen return palindrome_len # @param begin, an integer # @param end, an integer # @param palindromeCache, an array # @return a boolean #def _isPalindrome(self, begin, end, palindromeCache): ''' In palindromeCache, the index for s[index] and s[end] are index*2+1 and end*2+1 respectively. So in palindromeCache, the middle point of s[index] and s[end] is (index*2+1 + end*2+1) // 2, that is (index + end + 1). IF you remove this function and use a single statement instead, you could get a 30%-40% performance improvement or even more. ''' # return palindromeCache[begin + end + 1] - 1 >= (end - begin + 1) # @param s, a string # @return an integer def minCut(self, s): ''' Solve it in a dynamic programming method. ''' if len(s) == 0: return 0 palindromeCache = self._buildPalindromeCache(s) minCutEndingHere = [0] * len(s) for index in xrange(1, len(s)): if palindromeCache[index + 1] - 1 >= (index + 1): # The substring from beginning to here is a palindrome. No # cut is needed. minCut = 0 else: # We could add a cut between index and index - 1. minCut = 1 + minCutEndingHere[index-1] # Or the cut could be tried between tryingToCut and # tryingToCut - 1. for tryingToCut in xrange(1, index): # Only when s[tryingToCut : index+1] is palindrome, the # cut could be done. if palindromeCache[tryingToCut + index + 1] - 1 >= (index - tryingToCut + 1): minCut = min(minCut, \ 1 + minCutEndingHere[tryingToCut-1]) minCutEndingHere[index] = minCut return minCutEndingHere[-1]
Friday, September 19, 2014
Leetcode: Palindrome Partitioning II @Python
Use Manacher's algorithm with O(n)
O(n^2) Dynamic Programming is not optimal.
My Manacher's algorithm implementation got TLE.
I learn from the solution here.
Subscribe to:
Post Comments
(
Atom
)
No comments :
Post a Comment