132. Palindrome Partitioning II

相关问题:131. Palindrome Partitioning(Backtracking解法)

问题:(DP解法)

给定字符串,求最少切分几次,使得每一个切片都是回文字符串。

Example 1:
Input: s = "aab"
Output: 1
Explanation: The palindrome partitioning ["aa","b"] could be produced using 1 cut.

Example 2:
Input: s = "a"
Output: 0

Example 3:
Input: s = "ab"
Output: 1

Constraints:
1 <= s.length <= 2000
s consists of lower-case English letters only.

  

解法:DP(动态规划)

⚠️  注意:本问题不能用通用字符串dp[i][j]来表示字符串子串s[i~j]的所求结果。(状态转移较为难)

本问题设状态:

  • dp[i]:字符串s[0~i]需要最少切的次数。

base状态:

  • dp[i]:每个字符都是独立个体,最多切 i 刀(每对相邻字符之间都切)。

状态转移:

对于每一个位置 i:作为回文串中心

  • 奇数回文串:
    • 【i-j】...【i-1】【i】【i+1】...【i+j】,向两边扩展 j,若一直是回文串,那么可以缩减字符串 [i-j ~ i+j] 为一个切片。dp[i+j] = dp[i-j -1] + 1(回文串的前一个位置之前的最小cut数+1)
  • 偶数回文串:
    • 【i-j+1】...【i】|【i+1】...【i+j】,向两边扩展 j,若一直是回文串,那么可以缩减字符串 [i-j+1 ~ i+j] 为一个切片。dp[i+j] = dp[i-j+1 -1] + 1

当然,多次循环中,dp[i+j]自己也许有更小的值,因此,每次对自己求最小值。

代码参考:

 1 class Solution {
 2     //dp[i]:the minimum cuts the s[0~i] needs
 3 public:
 4     int minCut(string s) {
 5         int n = s.size();
 6         vector<int> dp(n+1, 0);
 7         //initial
 8         for(int i=0; i<=n; i++) dp[i] = i-1;//every char is seemed not Pal.
 9         //dp
10         for(int i=0; i<n; i++){//for each char as mid, expand to both side to check if a Pal.
11             for(int j=0; i-j>=0 && i+j<n; j++) {//odd: i-1 i i+1
12                 if(s[i+j]==s[i-j]) {//if Pal
13                     dp[i+j+1] = min(dp[i+j+1], dp[i-j]+1);
14                 } else {
15                     break;
16                 }
17             }
18             for(int j=1; i-j+1>=0 && i+j<n; j++) {//even: i | i+1
19                 if(s[i+j]==s[i-j+1]) {//if Pal
20                     dp[i+j+1] = min(dp[i+j+1], dp[i-j+1]+1);
21                 } else {
22                     break;
23                 }
24             }
25         }
26         
27         return dp[n];
28     }
29 };
原文地址:https://www.cnblogs.com/habibah-chang/p/14254148.html