Description:
Given a string s, partition s such that every substring of the partition is a palindrome.
Return all possible palindrome partitioning of s.
Example:
Input: "aab"
Output:
[
["aa","b"],
["a","a","b"]
]
Solutions:
Brute force:
class Solution:
def partition(self, string: str) -> List[List[str]]:
if not string:
return []
ret = []
for j in range(1,len(string)):
cache = string[:j]
if cache == cache[::-1]:
for recurr in self.partition(string[j:]):
ret.append([cache]+recurr)
if string == string[::-1]:
ret.append([string])
return ret

Brute force V2
class Solution:
def __init__(self,):
self.dic = {} # added this
def partition(self, string: str) -> List[List[str]]:
if not string:
return []
if string in self.dic:
return self.dic[string]
ret = []
for j in range(1,len(string)):
cache = string[:j]
if cache == cache[::-1]:
for recurr in self.partition(string[j:]):
ret.append([cache]+recurr)
if string == string[::-1]:
ret.append([string])
self.dic[string] = ret
return ret

Move and expand: recall https://leetcode.com/problems/longest-palindromic-substring/
class Solution:
def partition(self, string: str) -> List[List[str]]:
if not string:
return []
l = len(string)
archive = [[] for i in range(l)]
for i in range(l):
expand = 0
while i-expand > -1 and i+expand < l and string[i-expand] == string[i+expand]:
archive[i-expand].append(i+expand+1)
expand += 1
if i+1 < l and string[i] == string[i+1]:
expand = 1
while i-expand+1 > -1 and i+expand < l and string[i-expand+1] == string[i+expand]:
archive[i-expand+1].append(i+expand+1)
expand += 1
dic = {}
def helper(left):
if left == l:
return []
if left in dic:
return dic[left]
ret = []
for next_ in archive[left]:
cache = helper(next_)
if cache:
for recurr in cache:
ret.append([string[left:next_]] + recurr)
else:
ret.append([string[left:next_]])
dic[left] = ret
return ret
return helper(0)
Runtime: 68 ms, faster than 99.11% of Python3 online submissions for Palindrome Partitioning.
Memory Usage: 16.9 MB, less than 5.03% of Python3 online submissions for Palindrome Partitioning.
The iterative version (DFS) of the algorithm above:
class Solution:
def partition(self, string: str) -> List[List[str]]:
if not string:
return []
l = len(string)
archive = [[] for i in range(l)]
for i in range(l):
expand = 0
while i-expand > -1 and i+expand < l and string[i-expand] == string[i+expand]:
archive[i-expand].append(i+expand+1)
expand += 1
if i+1 < l and string[i] == string[i+1]:
expand = 1
while i-expand+1 > -1 and i+expand < l and string[i-expand+1] == string[i+expand]:
archive[i-expand+1].append(i+expand+1)
expand += 1
ret = []
stack = []
i = 0
pos = [0 for i in range(l)]
while True:
rng_l,rng_h = i,archive[i][pos[i]]
pos[i] += 1
stack.append(string[rng_l:rng_h])
i = rng_h
if i == l:
ret.append(copy.copy(stack))
i -= len(stack[-1])
stack.pop()
while stack and pos[i] >= len(archive[i]):
pos[i] = 0
i -= len(stack[-1])
stack.pop()
if i == 0 and pos[0] == len(archive[0]):
break
return ret
Runtime: 60 ms, faster than 100.00% of Python3 online submissions for Palindrome Partitioning.
Memory Usage: 14 MB, less than 14.46% of Python3 online submissions for Palindrome Partitioning.
More:
# Manacher's Algorithm 马拉车算法
Longest Palindromic Substring Manacher's Algorithm - Tushar Roy
geeksforgeeks manachers-algorithm-linear-time-longest-palindromic-substring-part-1/
geeksforgeeks manachers-algorithm-linear-time-longest-palindromic-substring-part-2