131. Palindrome Partitioning (Medium)

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

你可能感兴趣的:(131. Palindrome Partitioning (Medium))