题目

给你一个字符串 s,请你将 s 分割成一些子串,使每个子串都是回文。
返回符合要求的 最少分割次数 。
示例 1:
输入:s = “aab”
输出:1
解释:只需一次分割就可将 s 分割成 [“aa”,“b”] 这样两个回文子串。
示例 2:
输入:s = “a”
输出:0
示例 3:
输入:s = “ab”
输出:1
提示:
1 <= s.length <= 2000
s 仅由小写英文字母组成

2023年1月1日解答

class Solution {
 public:
 int minCut(string s) {
 m_c = s.length();
 vector<vector> is;
 is.assign(m_c, vector(m_c+1));
 for (int c = 0; c < m_c; c++)
 {
 //长度为1的字符串一定是回文
 is[c][1] = true;
 }
 for (int c = 0; c + 1 < m_c; c++)
 {
 is[c][2] = (s[c] == s[c + 1]);
 }for (int len = 3; len <= m_c; len++)
	 {
		 for (int c = 0; c + len - 1 < m_c; c++)
		 {
			 is[c][len] = is[c + 1][len - 2] && (s[c] == s[c + len - 1]);
		 }
	 }

	 //最少多少个回文构成
	 vector<int> dp(m_c + 1,INT_MAX);
	 dp[0] = 0;
	 for (int c = 0; c < m_c; c++)
	 {
		 for (int len = 1; len <= m_c; len++)
		 {
			 if (is[c][len] && (c+len <= m_c ))
			 {
				 dp[c + len] = min(dp[c + len], dp[c] + 1);
			 }
		 }
	 }
	 return dp[m_c] - 1;
 }
 int m_c;};

2023年8月

//马拉车计算回文回文
 class CPalindrome
 {
 public:
 //vOddHalfLen[i]表示 以s[i]为中心,且长度为奇数的最长回文的半长,包括s[i]
 //比如:“aba” vOddHalfLen[1]为2 “abba” vEvenHalfLen[1]为2
 static void Do(vector& vOddHalfLen, vector& vEvenHalfLen,const string& s)
 { 
 vector v;
 for (const auto& ch : s)
 {
 v.emplace_back(ch);
 v.emplace_back(‘*’);
 }
 v.pop_back();const int len = v.size();
	vector<int> vHalfLen(len);
	int center = -1, r = -1;
	//center是对称中心,r是其右边界(闭)
	for (int i = 0; i < len; i++)
	{
		int tmp = 1;
		if (i <= r)
		{
			int pre = center - (i - center);
			tmp = min(vHalfLen[pre], r - i + 1);
		}
		for (tmp++; (i + tmp - 1 < len) && (i - tmp + 1 >= 0) && (v[i + tmp - 1] == v[i - tmp + 1]); tmp++);
		vHalfLen[i] = --tmp;
		const int iNewR = i + tmp - 1;
		if (iNewR > r)
		{
			r = iNewR;
			center = i;
		}
	}

	vOddHalfLen.resize(s.length());
	vEvenHalfLen.resize(s.length());
	for (int i = 0; i < len; i++)
	{
		if (i & 1)
		{
			vEvenHalfLen[i / 2] = vHalfLen[i] / 2;
			
		}
		else
		{
			vOddHalfLen[i / 2] = (vHalfLen[i]+1) / 2 ;				
		}
	}
}};
 class Solution {
 public:
 int minCut(string s) {
 m_c = s.length();
 vector vOddHalfLen, vEvenHalfLen;
 CPalindrome::Do(vOddHalfLen, vEvenHalfLen,s);
 //邻接表
 vector<vector> vNeiBo(m_c+1);
 for (int i = 0; i < m_c; i++)
 {
 for (int len = 1; len <= vOddHalfLen[i]; len++)
 {
 const int cur = i - len + 1;
 const int next = i + len;
 vNeiBo[cur].emplace_back(next);
 }
 for (int len = 1; len <= vEvenHalfLen[i]; len++)
 {
 const int cur = i - len + 1;
 const int next = i + len+1;
 vNeiBo[cur].emplace_back(next);
 }
 }
queue<int> que;
	que.emplace(0);
	vector<int> vDis(m_c+1, -1);
	vDis[0] = 0;
	while (que.size())
	{
		const int cur = que.front();
		que.pop();
		const int curDis = vDis[cur];
		for (const auto& next : vNeiBo[cur])
		{
			if (-1 != vDis[next])
			{
				continue;
			}
			vDis[next] = curDis + 1;
			que.emplace(next);
		}
	}
	return vDis.back() - 1;
}
int m_c;
};


其它

视频课程

如果你觉得复杂,想从简单的算法开始,可以学习我的视频课程。

我的其它课程

测试环境

win7 VS2019 C++17

相关下载

doc版文档,排版好