LeetCode132:分割回文串

给定一个字符串 s,将 s 分割成一些子串,使每个子串都是回文串。

返回符合要求的最少分割次数。

示例:

输入: "aab"
输出: 1
解释: 进行一次分割就可将 s 分割成 ["aa","b"] 这样两个回文子串

与131题目类似,但是用递归的话在某些测例上会超时,因此考虑使用dp

使用dp,首先考虑回文的特点,从头与从尾开始,对应点的字符相等。

对一个i~j的字符串,如果我们已经判断完i+1~j-1是否为回文了,就不用重新一个个对应判断了。只要s[i]==s[j]且i+1~j-1是回文串,就可以直接判断它为回文。

因此:

状态定义:table[i][j]----->从i到j的子串是否为回文串

状态转移:

1).s[i]!=s[j]---->table[i][j]=0。i~j非回文

2).s[i]==s[j]:

  a).j-i<=1,即i和j重合或相邻,此时为回文串。

  b).table[i+1][j-1]如果为回文,则table[i][j]=1,否则非回文。

以上状态转移方程即可解得回文串的整个分布。

同时,题目要求的是解出最小分割次数。

在求解i~n-1中间的回文串状态时可以同时求出它的最小分割情况。

定义另外一个状态转移方程:

状态定义:dp[i]---->i~n-1中最小分割次数

状态转移方程:

1)i==n-1:在最后,此时应该为0

2)i!=n-1:dp[i]=min(dp[i],1+dp[j+1])---->i~j为回文串,i~n-1的最小分割次数应该是到j分割一次后,加上dp[j+1](也就是j+1~n-1的最小分割次数)。再通过一个min来选择其中最小的分割方案。

class Solution {
public:
    int minCut(string s) {
        vector<vector<int>> table(s.size(),vector<int>(s.size(),0));
		vector<int> dp(s.size());
		for(int i=s.size()-1;i>=0;i--)//aabaa
		{
			dp[i]=INT_MAX;
			for(int j=i;j<s.size();j++)
			{
				if(s[i]==s[j]&&((j-i<=1)||(table[i+1][j-1]==1)))
				{
					table[i][j]=1;
					if(j==s.size()-1)
						dp[i]=0;
					else
					{
						dp[i]=min(dp[i],1+dp[j+1]);
					}
				}
			}
		}
		return dp[0];
    }
};

  

原文地址:https://www.cnblogs.com/lxy-xf/p/11158445.html