力扣 1278. 分割回文串 III【区间dp】

好久没写了。无聊写一篇。


给你一个由小写字母组成的字符串 s,和一个整数 k。

请你按下面的要求分割字符串:


    首先,你可以将 s 中的部分字符修改为其他的小写英文字母。
    接着,你需要把 s 分割成 k 个非空且不相交的子串,并且每个子串都是回文串。


请返回以这种方式分割字符串所需修改的最少字符数。

 

示例 1:

输入:s = "abc", k = 2
输出:1
解释:你可以把字符串分割成 "ab" 和 "c",并修改 "ab" 中的 1 个字符,将它变成回文串。


示例 2:

输入:s = "aabbc", k = 3
输出:0
解释:你可以把字符串分割成 "aa"、"bb" 和 "c",它们都是回文串。

示例 3:

输入:s = "leetcode", k = 8
输出:0


 

提示:


    1 <= k <= s.length <= 100
    s 中只含有小写英文字母。


dp[i][j][k]表示将[i,j]区间内的字符串分割为k个回文串所需要修改的最小次数。

状态转移:

dp[beg][ed][i]=min(dp[beg][ed][i],min(dp[beg][j][i-1]+dp[j+1][ed][0],dp[beg][j][0]+dp[j+1][ed][i-1]));

就是将[beg,ed]分割为[beg,j],[j+1,ed]两个子区间,将其中一个区间不分割,其中一个分割k-1个回文串。取最小值。这样就能由子状态转移过来了。

可以先预处理一下[i,j]区间变为回文串最小修改次数。

同样是区间dp。

转移公式:

dp1[beg][ed]=dp1[beg+1][ed-1]+(s[beg]!=s[ed]);

就是将中间部分的dp值转移过来,判断两边是否相等。

贴个写的很烂的代码。

class Solution {
public:
    int palindromePartition(string s, int k) {
        int dp1[105][105];
        int dp[105][105][105];
        memset(dp,-1,sizeof dp);
        memset(dp1,0,sizeof dp1);
        for(int len=0;len<s.length();len++)
        {
            for(int beg=0;beg+len<s.length();beg++)
            {
                int ed=beg+len;
                if(len==0) dp1[beg][ed]=0;
                else dp1[beg][ed]=dp1[beg+1][ed-1]+(s[beg]!=s[ed]);
            }
        }
        for(int i=0;i<=100;i++)
        {
            for(int j=0;j<=100;j++)
            {
                for(int kk=0;kk<=100;kk++)
                {
                    dp[i][j][kk]=0x3f3f3f3f;
                }
            }
        }
        for(int i=0;i<s.length();i++)
        {
            for(int j=0;j<s.length();j++)
            {
                if(j>=i) dp[i][j][0]=dp1[i][j];
                else dp[i][j][0]=0x3f3f3f3f;
            }
        }
        for(int i=1;i<k;i++)
        {
            for(int beg=0;beg<s.length();beg++)
            {
                for(int ed=beg+i;ed<s.length();ed++)
                {
                    for(int j=beg;j<ed;j++)
                    {
                        dp[beg][ed][i]=min(dp[beg][ed][i],min(dp[beg][j][i-1]+dp[j+1][ed][0],dp[beg][j][0]+dp[j+1][ed][i-1]));
                    }
                }
            }
        }

        return dp[0][s.length()-1][k-1];
    }
};

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值