LeetCode132:分割回文串(DP、回文)
解题思路:有两个问点:1、如何快速当前字符串哪些的字串是回文;2、如何组合这些字串达到分割次数最少
针对问点1,可以开辟一个二维布尔数组 a[][],a[i][j]表示以索引i为起点,j为结束位置的字符串是否是回文串。那么有递推公式a[i][j] = a[i+1][j-1] &&(s[i]==s[j]) (i<j); a[i][j] = True (i>=j)。不难发现 a 数组可以在N*N的复杂度内完成。
针对问点2,本人一开始想的是一个(N*N*N)的算法,设置二维dp数组 dp[i][j]表示索引i为起点,j为结束位置的字符串的最小分割次数。枚举(i,j)区间,从而得到dp[0][N-1]的值,但是仔细观察,似乎可以去掉一个维度,设置一维dp数组 dp[i]表示以0为起点,i为结束位置的字符串的最小分割次数,枚举(0,i)区间,从而得到dp[N-1]的值,时间复杂度(N*N),于是得到状态转移方程 如果a[k][i]是回文串,那么dp[i] = max(dp[i],dp[k]+0+1),因为最终的分割次数,一定是和分割点的个数相同,即只有a[k][i]是回文串的时候才可能有状态转移。
1 class Solution: 2 def minCut(self, s): 3 length = len(s) 4 is_hui = [[0]*length for i in range(length)] 5 for i in range(length-1,-1,-1): 6 for j in range(0,length,1): 7 if i >=j: 8 is_hui[i][j] = 1 9 else: 10 is_hui[i][j] = is_hui[i+1][j-1] and (s[i]==s[j]) 11 inf = int(1e9) 12 dp = [inf for i in range(length)] 13 for i in range(length): 14 if is_hui[0][i]: 15 dp[i] = 0 16 #print(dp) 17 for i in range(length): 18 for k in range(0,i): 19 if is_hui[k+1][i]: 20 dp[i] = min(dp[i],dp[k]+1) 21 #print(dp) 22 return dp[-1]