题目描述
给出一个字符串s,分割s使得分割出的每一个子串都是回文串
计算将字符串s分割成回文分割结果的最小切割数
例如:给定字符串s=“aab”,
返回1,因为回文分割结果[“aa”,“b”]是切割一次生成的。
分析
设置两个变量 i 和 j,i 从字符串最后一个字符开始向前走,j 从 i 开始往后走到字符串结尾。设置数组dp[i]代表从 i 到s.length-1这段字符串要分割的最小次数,p[i][j]代表从i 到 j 的这一段字符串是不是回文串。如果 i 到 j 之间是回文,那就要找到 j+1到字符串最后的字符串分割成回文串的最小次数也就是p[j+1]。因当i=s.length-1,j=i,要找到p[i+1],所以p数组的大小是s.length+1,这也是为什么要从后往前算。
代码不易理解,根据例子s="aab"说一下:
置p[3]=-1
i = 2
…j = 2, 成回文,p[2] = p[3]+1 = 0 不用分割
i = 1
…j = 1,成回文,p[1] = p[2]+1 = 1
…j = 2, 不成回文,不操作
…最后p[1] = 1
i = 0
…j = 0, 回文,p[0] = p[1]+1 = 2
…j = 1, 回文,p[0] = min{p[0], p[2]+1} = 1
…j = 2, 不成回文,不操作
最后得出p[0]=1,即需要切割至少1次使其字串都是回文串
总结一下就是找到从i到s.length-1之间最小的分割次数,而更长串的分割次数由其字串的分割此处通过一定转换得来,所以串必须从短到长计算最小分割次数。状态转移方程:当i..j是回文, p[i] = min{p[i], p[j+1]+1} 判断i..j是不是回文:s.charAt[i]=s.charAt[j],且i和j是同一个或连在一起 或者 若不是以上情况则i+1..j-1是回文,也有套用子问题,因此还要维护dp[i][j]
代码
public