Palindrome Partitioning&II(回文字符串)

21 篇文章 0 订阅
6 篇文章 0 订阅

题意:找出一个字符串中的所有切割使得切割后的子串都是回文字符串。

首先想到一个简单的DP判断从i到j是否能组成回文。
设dp[i][j] = 1代表a[i]到a[j]组成的子串是回文,反之则不是。
转移方程:若dp[i+1][j-1] = 1且a[i] = a[j]则dp[i][j] = 1。
然后寻找所有切割可以使用DFS,深搜每个可能的分割。

代码如下:

class Solution {
public:
    int DFS(int index, vector<vector<bool> >& isPa, int sLen, vector<string>& tmp, string& s) {
        //表示寻找从index开始的回文字符子串
        if(index == sLen) {
            ans.push_back(tmp);
            return 1;
        }
        string tmpStr;
        for(int i = index;i < sLen;i++) {
            tmpStr += s[i];
            if(isPa[index][i]) {
                tmp.push_back(tmpStr);
                DFS(i+1, isPa, sLen, tmp, s);
                tmp.pop_back();
            }
        }
        return 0;
    }
    vector<vector<string>> partition(string s) {
        int sLen = s.size();
        if(sLen == 0)
            return ans;
        vector<vector<bool> > isPa(sLen, vector<bool>(sLen, 0));

        for(int i = sLen-1;i >= 0;i--) {
            isPa[i][i] = 1;
            for(int j = i+1;j < sLen;j++) {
                if((isPa[i+1][j-1] || i == j-1) && s[i] == s[j]) {
                    isPa[i][j] = 1;
                }
            }
        }
        vector<string> tmp;
        DFS(0, isPa, sLen, tmp, s);
        return ans;
    }
private:
    vector<vector<string> > ans;
};

对于第二个变式,需要加入另一个dp,因为一种切割必定有一个回文在它的最边缘。
设minCutNum[i]为从a[i]到a[N-1]组成的字符串的最小切割。
则转移方程为:若isPa[i][j],则minCutNum[i] = min(minCutNum[i], minCutNum[j+1]+1),其中i<=j<=N-1.

代码如下:

class Solution {
public:
    int minCut(string s) {
        int sLen = s.size();
        if(sLen == 0) return 0;
        vector<bool> isPa(sLen, 0);
        vector<int> minCutNum(sLen+1, INT_MAX-1);
        minCutNum[sLen] = -1;
        //minCutNum[i]表示从0到i的串的最小切割
        for(int i = sLen-1;i >= 0;i--) {
            for(int j = i;j < sLen;j++) {
                if((i == j || i == j-1 || isPa[j-1]) && s[i] == s[j]) {
                    isPa[j] = 1;
                    minCutNum[i] = min(minCutNum[j+1]+1, minCutNum[i]);
                }
            }
        }
        return minCutNum[0];
    }
};
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值