ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

LintCode刷题——分割回文串Ⅱ(序列型动态规划)

2021-04-03 12:02:47  阅读:124  来源: 互联网

标签:分割 int LintCode ++ && 刷题 个字符 回文


题目描述:

给定字符串 s, 需要将它分割成一些子串, 使得每个子串都是回文串.

最少需要分割几次?

样例

样例 1:

输入:
"a"
输出:
0
解释: 
"a" 本身就是回文串, 无需分割

样例 2:

输入:
"aab"
输出:
1
解释:
将 "aab" 分割一次, 得到 "aa" 和 "b", 它们都是回文串.


思路:

这里我们最主要的就是如何判断出指定区间的字符串为回文串,我们可以从前往后,以每一个字符为基石,让其往两边伸展,然后考虑奇偶性,因为一个回文串的长度要么是奇数,要么是偶数,就这两种情况,所以我们就可以定住每一个中间字符,向外扩展,判断这个字符串中哪些区间是回文串,哪些不是。并用一个二维的布尔类型数组记录每一个区间是否为回文串,接下来考虑最后一步就很容易了,我们知道最后一步一定是从第j个位置分割,将第j + 1个字符到最后一个字符划分为一个回文串,当我们考虑前i个字符的串是否为回文串时,我们就需要从第一个字符遍历到第i个字符,从中找到最少分割次数并更新。这样一来我们就把考虑前i个字符的串最少分割几次,转变为前j个字符的串最少分割几次。

转移方程:f[i] = min{f[i], f[j] + 1}

 

AC代码:

 1 public class Solution {
 2     /**
 3      * @param s: A string
 4      * @return: An integer
 5      */
 6     public int minCut(String s) {
 7         // write your code here
 8         if (s == null || s.length() == 0) {
 9             return 0;
10         }
11 
12         char[] c = s.toCharArray();
13         int n = c.length;
14 
15         boolean[][] isPalins = new boolean[n][n];
16 
17         // initialization
18         for (int i = 0; i < n; i++) {
19             for (int j = 0; j < n; j++) {
20                 isPalins[i][j] = false;
21             }
22         }
23 
24         // 定基准
25         for (int t = 0; t < n; t++) {
26             int i, j;
27             // 默认一个字符也是回文串
28             i = t;
29             j = t;
30 
31             // odd
32             while (i >= 0 && j < n && c[i] == c[j]) {
33                 isPalins[i][j] = true;
34                 i--;
35                 j++;
36             }
37 
38             i = t;
39             j = t + 1;
40             // even
41             while (i >= 0 && j < n && c[i] == c[j]) {
42                 isPalins[i][j] = true;
43                 i--;
44                 j++;
45             }
46         }
47 
48         // 定义状态:dp[i] 代表前i个字符中回文串的个数
49         int[] dp = new int[n + 1];
50 
51         // 初始化
52         dp[0] = 0;
53 
54         for (int i = 1; i <= n; i++) {
55             // 因为这里是取最小值,所以一开始要设为无穷大
56             // 任意一个字符串(空串除外)都能化成若干个回文串(因为单个字符就是一个回文串),所以一定可以分割出来,即这里设置为无穷大也就没啥问题
57             dp[i] = Integer.MAX_VALUE;
58             // 从第一个字符一直遍历到第i个字符。挨个判断,取最小值
59             for (int j = 0; j < i; j++) {
60                 if (isPalins[j][i - 1]) {
61                     // is Palin
62                     dp[i] = Math.min(dp[i], dp[j] + 1);
63                 }
64             }
65         }
66 
67         // 别忘了本题是让我们求最小需要分割几次,所有最后要-1
68         return dp[n] - 1;
69     }
70 }

 

标签:分割,int,LintCode,++,&&,刷题,个字符,回文
来源: https://www.cnblogs.com/pengsay/p/14613449.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有