Palindrome Partitioning II
Given a string s, partition s such that every substring of the partition is a palindrome.
Return the minimum cuts needed for a palindrome partitioning of s.
Example:
Input: "aab" Output: 1 Explanation: The palindrome partitioning ["aa","b"] could be produced using 1 cut.
这道题的意思是:给你一个字符串,至少需要切几下,使得切出来的子字符串都是回文串。只有一个字符的时候,它本身一个回文串,不需要切,切的次数为0。首先,我们要考虑某一段子字符串是不是回文串,然后再考虑切的问题。为了让切的次数最少,也就是说我们需要使得切出来的回文字符串尽量长。我们考虑用一个数组保存子字符串是否为回文,这里可以用动态规划的思想来得到这个数组。我们用dp[i][j]来表示字符串坐标i到j是否为回文。我们可以很轻易的得到如下递推公式:
$ dp[i][j] = max \left\{ \begin{aligned} & 1, i==j \\ & 1, i==j-1 \ and \ s[i]==s[j] \\ & 1, i < j-1 \ and \ dp[i+1][j-1]==1 \ and \ s[i] == s[j] \\ & 0, otherwise \end{aligned} \right. $
当i==j时,只有一个字符,是回文。当i==j-1,即两个字符相邻,判断两个字符是否相等,相等则为回文。当 i < j-1,就是说长度大于等于3,需要先判断dp[i+1][j-1]是不是回文,如果是回文,再判断s[i] == s[j]是否成立,成立的话就是回文。
得到dp矩阵后,如何去切也是个动态规划问题,定义数组cut[m], m = [0,1..., len(s)], cut[m]表示从坐标m到坐标len(s)需要切多少下。假如我们已经得到从坐标j到末尾需要切多少下的数据cut[j],并且dp[i][j]是回文,则从坐标i到末尾需要cut[i] = min(cut[j]+1, cut[i]),j = [i+1,...,len(s),len(s)+1]。也就是说得到cut[j]后,如果dp[i][j]是回文,那么cut[i]等于cut[j]+1(在cut[j]的基础上再砍一刀)。这个过程需要花费o($n^2$),我们可以在求解dp[i][j]的过程中去求解cut[i]。
$cut[i] = min(cut[j]+1, cut[i]), j = [i+1,...,len(s),len(s)+1]$
我们知道,如果只有一个元素,cut[len(s)-1]=0,那么cut[len(s)]=-1,这也是为什么我们从后面往前推的原因。下面是代码:
1 class Solution: 2 def minCut(self, s: str) -> int: 3 #需要使用dp保存子串是否为回文 4 #还需要数组保存cut保存到某一位置需要cut多少下 5 if not s: 6 return 0 7 length = len(s) 8 if length <= 1: 9 return 0 10 dp = [[0] * length for _ in range(length)] 11 #这里cut千万不能用0来赋值 12 cut = [length] * (length+1) 13 #从后往前推 14 cut[length] = -1 15 for i in range(length-1, -1, -1): 16 for j in range(i, length): 17 #相同位置 18 if i == j: 19 dp[i][j] = 1 20 #相邻位置 21 elif i == j-1 and s[i] == s[j]: 22 dp[i][j] = 1 23 else: 24 #相隔的位置,需要判断中间段是否为回文(两个字符相等也要咯) 25 if dp[i+1][j-1] == 1 and s[i] == s[j]: 26 dp[i][j] = 1 27 #如果i-j是回文,那么可以试试切一下看次数会不会比原来小 28 #cut[i]表示位置i到末尾需要切几下,如果i-j是回文,那么cut[i] = cut[j+1]+1,还要使得cut[i]的值最小 29 #当只有一个元素时,cut[i]为0 30 if dp[i][j] == 1: 31 cut[i] = min(cut[j+1]+1, cut[i]) 32 return cut[0]