首页 > 其他 > 详细

132. 分割回文串 II

时间:2021-04-10 22:36:12      阅读:22      评论:0      收藏:0      [点我收藏+]

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

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

 

示例 1:

输入:s = "aab"
输出:1
解释:只需一次分割就可将 s 分割成 ["aa","b"] 这样两个回文子串。
示例 2:

输入:s = "a"
输出:0
示例 3:

输入:s = "ab"
输出:1
 

提示:

1 <= s.length <= 2000
s 仅由小写英文字母组成

来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/palindrome-partitioning-ii
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。

 

题意:

  这是一道经典的DP题,可以采用二维DP(本题会超时),也可以进一步优化从而使DP降到一维。因为二维DP相对容易理解些,所以我们先从二维DP来计算。

题解:

  palindromeTable[i][j]:用来表示s[i][j]是否是一个回文字符串,它有三种状态:

  • length = 1时:
    • palindromeTable[i][i] = true  
  • length = 2时:
    • if s[i] == s[i+1]: palindromeTable[i][j] = true
    • else: palindromeTable[i][j] = false
  • length > 2时:
    • if s[i] == s[j]: palindromeTable[i][j] = palindromeTable[i-1][j-1]
    • else: palindromeTable[i][j] = false  

  dpTable[i][j]:用来表示将s[i][j]拆分成都是回文的子串所需要的最少拆分次数,它也是有三种状态:

  • length = 1时:
    • dpTable[i][i] = 0    
  • length = 2时:
    • if s[i] == s[i+1]: dpTable[i][i+1] = 0
    • else: dpTable[i][i+1] = 1 
  • length > 2时:
    • if palindromeTable[i][j] = true: dpTable[i][j] = 0
    • else: dpTable[i][j] = min(dpTable[i][j], dpTable[i][k] + dpTable[k+1][j] + 1),其中i < k < j 

  最后的结果就是DPTable[0][len-1]。

技术分享图片

 

代码:

#include <iostream>
#include <string>
#include <vector>

using namespace std;

const int inf = 0x7fffffff;

void creatPalindromeTable(const string& s, vector<vector<bool> >& table) {
    int len = s.length();
    // length = 1
    for (int i = 0; i < len; ++i) table[i][i] = true;
    // length = 2
    for (int i = 0; i < len - 1; ++i)
        if (s[i] == s[i + 1]) table[i][i + 1] = true;
    // length > 2
    for (int i = 3; i <= len; ++i) {
        for (int j = 0; j + i <= len; ++j) {
            if (s[j] == s[j + i - 1]) {
                table[j][j + i - 1] = table[j + 1][j + i - 2];
            }
        }
    }
}

void creatDpTable(const string& s, vector<vector<int> >& dpTable) {
    int len = s.length();
    vector<vector<bool> > palindromeTable(len, vector<bool>(len, false));
    creatPalindromeTable(s, palindromeTable);
    // length = 1
    for (int i = 0; i < len; ++i) dpTable[i][i] = 0;
    // length = 2
    for (int i = 0; i < len - 1; ++i)
        if (s[i] == s[i + 1])
            dpTable[i][i + 1] = 0;
        else
            dpTable[i][i + 1] = 1;
    // length > 2
    for (int i = 3; i <= len; ++i) {
        for (int j = 0; j + i <= len; ++j) {
            if (palindromeTable[j][j + i - 1])
                dpTable[j][j + i - 1] = 0;
            else
                for (int k = j; k < j + i - 1; ++k)
                    dpTable[j][j + i - 1] =
                        min(dpTable[j][j + i - 1],
                            dpTable[j][k] + dpTable[k + 1][j + i - 1] + 1);
        }
    }
}

int main() {
    string s;
    cin >> s;
    int len = s.length();
    vector<vector<int> > dpTable(len, vector<int>(len, inf));
    creatDpTable(s, dpTable);
    cout << dpTable[0][len - 1] << endl;
    return 0;
}

 

  这样做提交的时候会报超时,因为这道题的最后结果只需要dpTable就可以了,所以我们可以想办法对dpTable进行降维,使dpTable默认从0开始dpTable[i]即表示dpTable[0][i]。这样的话就可以把时间复杂度从O(n^3)降到O(n^2)。

  dpTable[i]:代表从0到i所需的最小分割次数,共有两种状态。

  • if palindromeTable[0][i] = true: dpTable[i] = 0
  • else : dpTable[i] = min(dpTable[i], dpTable[j]+1), 其中 0 < j < i。  

代码:

#include <iostream>
#include <string>
#include <vector>

using namespace std;

const int inf = 0x7fffffff;

void creatPalindromeTable(const string& s, vector<vector<bool> >& table) {
    int len = s.length();
    // length = 1
    for (int i = 0; i < len; ++i) table[i][i] = true;
    // length = 2
    for (int i = 0; i < len - 1; ++i)
        if (s[i] == s[i + 1]) table[i][i + 1] = true;
    // length > 2
    for (int i = 3; i <= len; ++i) {
        for (int j = 0; j + i <= len; ++j) {
            if (s[j] == s[j + i - 1]) {
                table[j][j + i - 1] = table[j + 1][j + i - 2];
            }
        }
    }
}

void creatDpTable(const string& s, vector<int>& dpTable) {
    int len = s.length();
    vector<vector<bool> > palindromeTable(len, vector<bool>(len, false));
    creatPalindromeTable(s, palindromeTable);

    for (int i = 0; i < len; ++i) {
        if (palindromeTable[0][i])
            dpTable[i] = 0;
        else {
            for (int j = 0; j < i; ++j) {
                if (palindromeTable[j + 1][i])
                    dpTable[i] = min(dpTable[i], dpTable[j] + 1);
            }
        }
    }
}

int main() {
    string s;
    cin >> s;
    int len = s.length();
    vector<int> dpTable(len, inf);
    creatDpTable(s, dpTable);
    cout << dpTable[len - 1] << endl;
    return 0;
}

 

132. 分割回文串 II

原文:https://www.cnblogs.com/h-hkai/p/14642068.html

(0)
(0)
   
举报
评论 一句话评论(0
关于我们 - 联系我们 - 留言反馈 - 联系我们:wmxa8@hotmail.com
© 2014 bubuko.com 版权所有
打开技术之扣,分享程序人生!