题目描述:
给定一个字符串 s,将 s 分割成一些子串,使每个子串都是回文串。
返回符合要求的最少分割次数。
示例:
输入: “aab”
输出: 1
解释: 进行一次分割就可将 s 分割成 [“aa”,“b”] 这样两个回文子串。
方法1:
主要思路:
(1)先将字符串各个可能组成回文的子字符串标识出来;
(2)对标识出来的各个回文字符串进行动态规划,则dp[ i ] 表示长度为 i 的子字符串中,包含的可能组成的回文字符串的数量,则对于 dp[ i +1],可以将在0到i范围内的 j,判断子字符串 j,i能否是回文子串,若是,则可以更新dp[i+1]=min(dp[i+1],dp[j]+1);
(3)对于最后的返回值,则为dp.back()-1,因为dp 的最后一个元素为字符串内可以分割成最少的回文的数量,则分割的次数为回文的数量减去1;
class Solution {
public:
int minCut(string s) {
//标识字符串 s 包含的各种回文字符串
vector<vector<bool>> sign(s.size(),vector<bool>(s.size(),false));
for(int i=0;i<s.size();++i){//使用中心扩散的方法,找出各个可能的回文字符串
sign[i][i]=true;//单个的字符是回文
//以当前字符为中心进行判断
int left=i-1;
int right=i+1;
while(left>=0&&right<s.size()&&s[left]==s[right]){
sign[left][right]=true;
--left;
++right;
}
//当前字符不为中心进行判断
left=i;
right=i+1;
while(left>=0&&right<s.size()&&s[left]==s[right]){
sign[left][right]=true;
--left;
++right;
}
}
//动态规划数组初始化为最多可能的回文的数量,既字符串的长度
vector<int> dp(s.size()+1,s.size());
dp[0]=0;//字符串长度为0时,则为0个回文子串
for(int i=0;i<s.size();++i){
for(int j=0;j<=i;++j){
if(sign[j][i]){//从j到i是回文
dp[i+1]=min(dp[i+1],dp[j]+1);//则更新可能的更小的回文字符串的数量
}
}
}
return dp.back()-1;//返回分割的次数
}
};