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.

For example, given s = "aab",
Return 1 since the palindrome partitioning ["aa","b"] could be produced using 1 cut.

问题:对给定的字符串进行分割,使得每个子字符串都是回文的。求最小的分割情况。

假设将 s 分割为两段,[0, i-1], [i, n-1],若 [0, i-1] 为回文字符串,则  ( [i, n-1] 的最小分割次数字符串数 + 1 )  便是 s 以 i 为分割点最小分割情况的子字符串数。

将 i 从 1 到 n-1 遍历一边,便得到 s 依次以 i 为分割点得最小分割情况的子字符串数,其中最小的便是原问题的解。

利用 DP 思路,存储中间结构,避免重复的计算。 tailMinCutSC[i] 表示从 下标i 到结尾的最小分割情况的子字符串数。

算法思路是正确的,但是扔到 LeetCode 却超时了。接下来进行多次优化:

1. 求解子问题时,将 substr 的操作改为了 传引用 & 和 下标来表示,优化效果不明显。仅从 1204 ms 加快到 936 ms 。

2. 求解 s[i, j] 是否是回文时,每次从 i 到 j 扫一遍,耗时太长。采用二维数组 PalinVV 记录全部可能的结果,减低时间复杂度。优化前的耗时我不太会分析,通过程序记录开看,是远远超过 O(n*n)的,进行这步优化后,使得整个算法时间复杂降为 O(n*n)。

3.  实现第2 步优化,本身也是一个 DP 思路。PalinVV[i][k](i <= k),表示 s[i,k] 是否是回文,可以根据 PalinVV[i+1][k-1] 结果快速得到。对于 PalinVV 二维表格,从下往上计算,方便利用之前的结果。

vector<int> tailMinCutSC;

const int NEWONE = -;

vector<vector<bool>> PalinVV;

/**
* 判断字符串 s 的[sIdx, eIdx] 部分字符是否是回文字符串。
*
*/
bool isPalindrome(const string& s, int sIdx, int eIdx){ return PalinVV[sIdx][eIdx];
} /**
* 判断字符串 s 的[sIdx, eIdx] 部分字符是否是回文字符串。
*
*/
bool isPalindrome(const string& s, int sIdx){ return isPalindrome(s, sIdx, (int)s.size()-);
} /**
* 对 s 字符串 [sIdx, n]部分进行回文分割,返回最小分割情况的子字符串数。
*
*/
int palindromeCut(const string& s, int sIdx){ if (isPalindrome(s, sIdx)) { tailMinCutSC[sIdx] = ;
return ;
} int minCutSC = (int)s.size() - sIdx; for (int i = sIdx + ; i < s.size(); i++) {
bool leftP = isPalindrome(s, sIdx, i-);
if (leftP == false) {
continue;
}
int rightSC;
if (tailMinCutSC[i] != NEWONE) {
rightSC = tailMinCutSC[i];
}else{
rightSC = palindromeCut(s, i);
tailMinCutSC[i] = rightSC;
} int oneSolution = rightSC + ;
minCutSC = min(minCutSC, oneSolution); } return minCutSC;
} /**
* 求字符串 s 的任意子字符串是否是回文,结果存于二维布尔数组
* 求解全部可能的子字符串,符合 overlapping & optimal subcontructure,可以采用 DP 思想加速求解。
*
*/
void calculatePalinVV(string& s){ vector<vector<bool>> vvtmp(s.size(), vector<bool>(s.size())); PalinVV = vvtmp; for (int i = (int)s.size()-; i >= ; i--) {
PalinVV[i][i] = ;
} for (int i = (int)s.size()-; i >= ; i--) {
if (s[i] == s[i+]) {
PalinVV[i][i+] = ;
}else{
PalinVV[i][i+] = ;
}
} for (int i = (int)s.size()-; i >= ; i--) {
for (int k = (int)s.size()-; k >= i + ; k--) {
if (s[i] == s[k] && PalinVV[i+][k-]) {
PalinVV[i][k] = ;
}else{
PalinVV[i][k] = ;
}
}
}
} int minCut(string s) { calculatePalinVV(s); vector<int> tmp(s.size(), NEWONE);
tailMinCutSC = tmp; int minSC = palindromeCut(s, ); tailMinCutSC[] = minSC; int minCutPoint = minSC - ; return minCutPoint;
}

参考资料 :

[LeetCode] Palindrome Partitioning II, Solution, 水中的鱼

[LeetCode] Palindrome Partitioning II 解题笔记的更多相关文章

  1. LeetCode: Palindrome Partitioning II 解题报告

    Palindrome Partitioning II Given a string s, partition s such that every substring of the partition ...

  2. [leetcode]Palindrome Partitioning II @ Python

    原题地址:https://oj.leetcode.com/problems/palindrome-partitioning-ii/ 题意: Given a string s, partition s  ...

  3. [LeetCode] Palindrome Partitioning II 拆分回文串之二

    Given a string s, partition s such that every substring of the partition is a palindrome. Return the ...

  4. Leetcode: Palindrome Partitioning II

    参考:http://www.cppblog.com/wicbnu/archive/2013/03/18/198565.html 我太喜欢用dfs和回溯法了,但是这些暴力的方法加上剪枝之后复杂度依然是很 ...

  5. LeetCode:Palindrome Partitioning,Palindrome Partitioning II

    LeetCode:Palindrome Partitioning 题目如下:(把一个字符串划分成几个回文子串,枚举所有可能的划分) Given a string s, partition s such ...

  6. leetcode@ [131/132] Palindrome Partitioning & Palindrome Partitioning II

    https://leetcode.com/problems/palindrome-partitioning/ Given a string s, partition s such that every ...

  7. 【leetcode】Palindrome Partitioning II

    Palindrome Partitioning II Given a string s, partition s such that every substring of the partition ...

  8. leetcode 131. Palindrome Partitioning 、132. Palindrome Partitioning II

    131. Palindrome Partitioning substr使用的是坐标值,不使用.begin()..end()这种迭代器 使用dfs,类似于subsets的题,每次判断要不要加入这个数 s ...

  9. 【LeetCode】132. Palindrome Partitioning II

    Palindrome Partitioning II  Given a string s, partition s such that every substring of the partition ...

随机推荐

  1. SQL Server 2008文件与文件组的关系

    此文章主要向大家讲述的是SQL Server 2008文件与文件组,其中包括文件和文件组的含义与关系,文件.文件组在实践应用中经常出现的问题,查询文件组和文件语句与MSDN官方解释等相关内容的介绍. ...

  2. 『重构--改善既有代码的设计』读书笔记---Duplicate Observed Data

    当MVC出现的时候,极大的推动了Model与View分离的潮流.然而对于一些已存在的老系统或者没有维护好的系统,你都会看到当前存在大把的巨大类----将Model,View,Controller都写在 ...

  3. gnome中文翻译之po

    文件类型: po: 用msginit分析pot文件,生成各语言对应的po文件,比如中文的zh_CN.po. mo: 用msgfmt将po文件编译生成mo文件,这是二进制文件,不能直接编辑. gmo: ...

  4. php完整验证码代码

    <?php require_once 'string.func.php'; //通过GD库做验证码 /** *添加验证文字 * @param int $type * @param int $le ...

  5. Python 手册——Python的非正式介绍

    在后面的例子中,区分输入和输出的方法是看是否有提示符(“>>> ”和“.. ”):想要重复这些例子的话,你就要在提示符显示后输入所有的一切:没有以提示符开始的行,是解释器输出的信息. ...

  6. Python定义常量

    用Python实现常量 定义 # coding=utf-8 # const.py class ConstAssignError(Exception): pass class _const(object ...

  7. Dictionary通过Value找到它的key

    private void GetDicKeyByValue() { Dictionary<string, string> dic = new Dictionary<string, s ...

  8. Ogre内部渲染流程分析系列

    come from:http://blog.csdn.net/weiqubo/article/details/6956005 要理解OGRE引擎,就要理解其中占很重要位置的 Renderable接口, ...

  9. 十大响应式Web设计框架

    http://www.csdn.net/article/2014-05-13/2819739-responsive-frameworks-for-web-design 对于设计师而言,网站设计中的任意 ...

  10. 使用ListItem给DropDownList填充数据

    global::日积月累啥的啊.DBhelper db = new 日积月累啥的啊.DBhelper(); ListItem[] item=]; DataTable dt=db.GetDataTabl ...