[程序员代码面试指南]字符串问题-回文最少分割数(DP)

Posted coding-gaga

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了[程序员代码面试指南]字符串问题-回文最少分割数(DP)相关的知识,希望对你有一定的参考价值。

问题描述

给定一个字符串,输出把它全部切成回文子串的最小分割数。
例:str="ACDCDCDAD",输出2。

解题思路

DP

存储结构

  • dp数组dp[len+1],dp[i]表示子串str[I:len]至少需要切割几次,才能都切割成回文串。对应的,循环从右至左进行。
    • 注意 dp[i]的含义完全可以做对称更改,循环也变为从前向后即可。
    • 此外,为了保证int cutTime=dp[j+1]+1;//句的顺利执行,且dp[len-1]=0,palStr=true.dp数组多开一位,并初始化其为-1。
  • 二维boolean数组palStr[len][len]描述palStr[i][j]是否是回文串

状态转移方程

遍历j从i到len-1,若j到len-1是回文串,则dp[i]=dp[j+1]+1是候选最优解之一。故有dp[i]=min{dp[j+1]+1},i<=j<=len-1且palStr[i+1][j-1]是回文串

判断回文子串

  • 三种情况:str只有一个字符/str有两个字符且相等/str[i+1][j-1]为回文串且str[i]==str[j],这三种情况可合并写为str[i]==str[j]&&(j-i<=1||palStr[i+1][j-1])
  • 注意:我们需要在求palStr[I][j]的时候已知palStr[I+1][j+1]的值,根据dp[i]的含义及对应的循环顺序,我们可以保证该条件。经尝试,内部j的循环方向是无所谓的。

代码 时间复杂度O(n^2)

public class Main {
    public static void main(String args[]) {
        String str="acdcdcdad";
        int time=cutTimes(str);
        System.out.println(time);
    }
    
    public static int cutTimes(String str) {
        if(str==null||str=="") {
            return 0;
        }
        
        int len=str.length();
        int[] dp=new int[len+1];//
        dp[len]=-1;//
        boolean[][] palStr=new boolean[len][len];
        
        for(int i=0;i<len;++i) {
            for(int j=0;j<len;++j) {
                palStr[i][j]=false;
            }
        }
        
        for(int i=len-1;i>=0;--i) {
            dp[i]=Integer.MAX_VALUE;
            for(int j=i;j<len;++j) {
//          for(int j=len-1;j>=i;--j) {
                if(str.charAt(i)==str.charAt(j)&&(j-i<=1||palStr[i+1][j-1])) {
                    palStr[i][j]=true;
                    int cutTime=dp[j+1]+1;//
                    if(cutTime<dp[i]) {
                        dp[i]=cutTime;
                    }
                }
            }
        }
        return dp[0];
    }
}

以上是关于[程序员代码面试指南]字符串问题-回文最少分割数(DP)的主要内容,如果未能解决你的问题,请参考以下文章

[程序员代码面试指南]递归和动态规划-换钱的最少货币数

Palindrome Partitioning LightOJ - 1044(回文串最小分割数,O(n^2)预处理子串是否回文)

9.18 判断一个数是否是回文数

如何将字符串转换为具有最少删除字符串字符数的回文?

分割回文串 II · Palindrome Partitioning II

左神算法书籍《程序员代码面试指南》——2_06判断一个链表是否为回文结构