问题描述
给定一个字符串s, 分割s使得分割出的每一个子串都是回文串.
计算将字符串s分割成回文分割结果的最小切割数
例如: 给定字符串 s = “aab”;
返回 1. 因为回文分割结果[“aa”, “b”]是切割一次生成的
回文串就是指正着读和反着读都一样的字符串, 比如 “level”
用F(i)表示到第 i 个字符需要的最小分割数
给定一个 j < i, 如果此时从 j + 1 到 i 是一个回文串, 并且假定我们已经知道从第 1 个字符到 第 j 个字符的最小切割数,那么我们就可以找到这个状态递推公式
也就是 F(i) = min(F(i), F(j) + 1)
此时能保证从第 1 个字符到第 j 个字符是回文串
从j + 1到 i 也是回文串
并且1到 j 也就是到第 j 个字符的最小切割数已知,则F(i) = F(j) + 1;
由于 i 个字符的最大切割次数为 i - 1,初始化的时候直接使用F(i) = i - 1即可
代码如下:
class Solution {
public:
int minCut(string s) {
int len = s.size();
vector<int> v;
for (int i = 0; i < len + 1; ++i)
{
v.push_back(i - 1);
}
for (int i = 1; i < len + 1; ++i)
{
for (int j = 0; j < i; ++j)
{
//判断从 j + 1 到 i 是否是一个回文串
//注意其在string中的索引需要减1
if (IsPalindrome(s, j, i - 1))
{
v[i] = min(v[i], v[j] + 1);
}
}
}
return v[len];
}
//判断回文串的函数
bool IsPalindrome(string s, int i, int j)
{
while (i < j)
{
if (s[i] != s[j])
{
return false;
}
i++;
j--;
}
return true;
}
};