【palindrome partitioning II】cpp
题目:
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.
代码:
class Solution {
public:
int minCut(string s)
{
const int len = s.size();
vector<vector<bool> > p(len, vector<bool>(len,false));
Solution::allPalindrome(p, s);
vector<int> dp(len, INT_MAX);
dp[] = ;
for ( int i = ; i < len; ++i )
{
for ( int j = i; j >= ; --j )
{
if ( j== )
{
if ( p[j-][i] )
{
dp[i] = ;
break;
}
}
if ( p[j][i] )
{
dp[i] = std::min(dp[i], dp[j-]+);
}
}
}
return dp[len-];
}
// palindromes[i][j] denotes if s[i:j] is palindrome
static void allPalindrome(vector<vector<bool> >& palindromes, string& s)
{
for ( int i = palindromes.size()-; i >= ; --i )
{
for ( int j = i; j <= palindromes.size()-; ++j )
{
if ( (i+>j- && s[i]==s[j]) || (i+<=j- && s[i]==s[j] && palindromes[i+][j-]) )
{
palindromes[i][j] = true;
}
}
}
}
};
tips:
通过此题掌握了动态规划的一些套路。
动规的核心在于求解两个重要的变量
p[i][j] : 代表s[i]到s[j]是否构成一个回文
dp[i] : 标记s[0]到s[i]的最小回文分割
接下来阐述上述两个变量的生成过程:
1. p[i][j]
正确地求出p[i][j]就是成功的一半,第一次没有AC主要就是p[i][j]求错了。在这里详细记录一下正确的求解过程
第一步,要明确p[i][j]的含义,即s[i]到s[j]是否为回文。
第二步,把求解p[i][j]转化为状态转移方程,即p[i][j] = f(p[k][v]) (k<=i, v<=j, 且k==i,v==j不同时成立)。
这个看起来是一个二维的dp方程,条件什么的比较麻烦,但实际上方程比较简单。
p[i][j] = s[i]==s[j] && p[i+1][j-1]
相当于两个条件
a) 首尾相等
b) 中间子字符串是回文
当然,还要处理一些极端情况:
极端情况1:i==j
极端情况2:i==j+1
把极端的case处理好,就可以开始dp过程了
另,因为是回文(正反都一样)所以求解p的时候,只用求解上三角阵就可以了。
2. dp[i]
之前理解dp有一个误区:认为dp[i]由dp[i-1]一步推倒过来。这是非常不正确的。
正确的理念应该是:dp[i]应该由dp[0]~dp[i-1]导出。(即当前结受到已计算出的中间结果影响,只不过有时候用不到回溯那么靠前的中间结果,只用回溯上一步的结果dp[i-1]就可以了)
然而,这道题正好不能只回溯一步,而是要回溯所有之前步骤。
既然要回溯,就要有规则,规则要保证不重不漏。这里我们关注的点是s[i]:即,我们求dp[i]则s[i]是一定要包含在其中某个回文字串中的,具体如下:
s[i]自己是一个回文子串
s[i-1:i]构成回文子串
s[i-2:i]构成回文子串
...
s[0:i]构成回文串
上述的i+1种情况如果都讨论到了,则dp[i]也就求出来了。
具体阐述如下:
s[0] ... s[i-2] s[i-1] s[i]:如果p[i-1][i]==true (即s[i-1]~s[i]是回文),则如果切割点在s[i-2]与s[i-1]之间,则dp[i] = min ( dp[i] , dp[i-2]+1)
....
s[0] ... s[j-1] s[j] ... s[i]:如果p[j][i]==true,则如果切割点在dp[i] = min ( dp[i], dp[j-1]+1)
s[0] ... s[i] :如果p[0][i]==true,则不用切割也可以,故最小切割数是0。
按照上述的思路,再处理一下corner case,代码也就出来了。
=====================================
这份代码在处理corner cases上面做的不太好,有很多可以避免的冗余。但是先保留着吧,毕竟是原始的思考思路。第二遍刷的时候,再精细化一些corner case。
======================================
第二次过这道题,看了第一次做的思路,代码重新写了一遍,比第一次过的时候要简洁一些。
class Solution {
public:
int minCut(string s)
{
const int n = s.size();
vector<vector<bool> > p(n, vector<bool>(n,false));
Solution::isPalindrome(p, s);
int dp[n];
fill_n(&dp[], n, );
for ( int i=; i<n; ++i )
{
if ( p[][i] )
{
dp[i]=;
continue;
}
int cuts = INT_MAX;
for ( int j=i; j>; --j)
{
if ( p[j][i] ) cuts = min(cuts, dp[j-]+);
if ( cuts== ) break;
}
dp[i] = cuts;
}
return dp[n-];
}
static void isPalindrome(vector<vector<bool> >& p, string s)
{
for ( int i=; i<s.size(); ++i )
{
for ( int j=; j<=i; ++j )
{
if ( i-j< )
{
p[j][i] = s[i]==s[j];
}
else
{
p[j][i] = s[i]==s[j] && p[j+][i-];
}
}
}
}
};
【palindrome partitioning II】cpp的更多相关文章
- 【Word Break II】cpp
题目: Given a string s and a dictionary of words dict, add spaces in s to construct a sentence where e ...
- 【Unique Paths II】cpp
题目: Follow up for "Unique Paths": Now consider if some obstacles are added to the grids. H ...
- 【Path Sum II】cpp
题目: Given a binary tree and a sum, find all root-to-leaf paths where each path's sum equals the give ...
- 【Spiral Matrix II】cpp
题目: Given an integer n, generate a square matrix filled with elements from 1 to n2 in spiral order. ...
- 【Jump Game II 】cpp
题目: Given an array of non-negative integers, you are initially positioned at the first index of the ...
- 【Combination Sum II 】cpp
题目: Given a collection of candidate numbers (C) and a target number (T), find all unique combination ...
- 【Word Ladder II】cpp
题目: Given two words (start and end), and a dictionary, find all shortest transformation sequence(s) ...
- 【Single Num II】cpp
题目: Given an array of integers, every element appears three times except for one. Find that single o ...
- 【leetcode】Palindrome Partitioning II
Palindrome Partitioning II Given a string s, partition s such that every substring of the partition ...
随机推荐
- 菜鸟 学注册机编写之 “MD5”
测试环境 系统: xp sp3 调试器 :od 1.10 sc_office_2003_pro 高手不要见笑,仅供小菜玩乐,有不对或不足的地方还请多多指教,不胜感激! 一:定位关键CALL 1. 因 ...
- cocos2d-x-2.2.0_win7+vs2010搭建_eclipse+ndk-r9+cygwin搭建_教程以及编译问题汇总
声明:我是才用c/c++和cocos2d-x的如果有错误欢迎指出 文章内容我亲测过可以通过,同时我也会一直更新内容 感谢那些把自己的东西分享出来的人 原文地址:http://www.cnblogs.c ...
- 使用C#版OpenCV进行圆心求取
OpenCVSharp是OpenCV的.NET wrapper,是一名日本工程师开发的,项目地址为:https://github.com/shimat/opencvsharp. 该源码是 BSD开放协 ...
- C#访问修改符
修饰符可以指定访问的可见性,还可以指定其本质.(文章摘自<C#高级编程(第9版)>以及Microsoft) 1. 可见性修饰符 public:应用于所有类型或成员,即任何代码均可以访问该项 ...
- xp_delete_files不起作用解决方法
xp_delete_file用来删除数据库的备份文件和维护计划文本报告.示例: ,N'D:\Backup\Diff',N'bak',N'2019-05-29T10:03:41' 第一个参数表示文件类型 ...
- 使用Java程序消费SAP Leonardo的机器学习API
以sap leonardo作为关键字在微信上搜索,能搜到不少文章.但是我浏览了一下,好像没有发现有从具体编程角度上来介绍的.所以我就贡献一篇. 需求 开发一个Java程序,用户可以指定一张图片,该Ja ...
- Aizu 2300 Calender Colors(暴力)
状压以后,直接暴力枚举,2^20约等于1e6,而且满足bitcount = m的状态很少. #include<bits/stdc++.h> using namespace std; +; ...
- 【洛谷3796】【模板】AC自动机(加强版)
点此看题面 大致题意: 一道模板题,给你\(N\)个模式串和一个文本串,要你求出在文本串中出现次数最多的若干个模式串并输出它们. \(AC\)自动机 都说了是\(AC\)自动机的模板题,做法肯定是\( ...
- 【洛谷2051】[AHOI2009] 中国象棋(烦人的动态规划)
点此看题面 大致题意: 让你在一张\(N*M\)的棋盘上摆放炮,使其无法互相攻击,问有多少种摆法. 辟谣 听某大佬说这是一道状压\(DP\)题,于是兴冲冲地去做,看完数据范围彻底懵了:\(N≤100\ ...
- JS中的async/await的执行顺序详解
虽然大家知道async/await,但是很多人对这个方法中内部怎么执行的还不是很了解,本文是我看了一遍技术博客理解 JavaScript 的 async/await(如果对async/await不熟悉 ...