LeetCode1278. 分割回文串 III--动态规划

  1. 分割回文串 III

给你一个由小写字母组成的字符串 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 中只含有小写英文字母。

题解:

看数据量最多100就可以猜到是动态规划方向的题目,然后开始考虑,定义数组dp[n][k]表示对字符串s的区间[0,n]划分成k段,并且k段都为回文串所需要的最小的替换的字符数目,于是可以知道有如下关系:
dp[n][k]=dp[x][k-1]+cost[x+1][n];
其中x取值范围在[k-2,n]之间,因为字符串下标从0开始,在k-1基础上再减1,得到k-2,cost[l][r]表示字符串区间[l,r]直接构成回文串需要替换的字符数目,这个关系没有任何问题,但是x取多少我们不知道,所以x在区间[k-2,n]之间循环跑一遍,然后得到dp[x][k-1]+cost[x+1][n]最小的结果,便是答案,还真是挺有趣的。

AC代码

class Solution {
public:
    int cost_fun(string s,int l,int r)//用来计算区间[l,r]字符串构成回文串需要修改的字符个数
    {
        int ans=0;
        for(int i=l,j=0;i<=(l+r)/2;i++,j++)
        {
            if(s[i]!=s[r-j])ans++;
        }
        return ans;
    }
    int cost[110][110];
    int dp[110][110];
    int palindromePartition(string s, int k) {
        for(int i=0;i<s.length();i++)
        {
            for(int j=i;j<s.length();j++)
            cost[i][j]=cost_fun(s,i,j);
        }
        for(int i=0;i<s.length();i++)
        {
            for(int j=1;j<=k;j++)
            dp[i][j]=1e9;初始化
        }
        //得到区间[0,x]构成一个回文串需要替换的字符数目
        for(int i=0;i<s.length();i++)
        dp[i][1]=cost[0][i];
        //开始拓展,i表示分成几个区间,j表示区间[0,j]
        for(int i=2;i<=k;i++)
        {
            for(int j=i-1;j<s.length();j++)
            {
                for(int x=i-2;x<j;x++)
                dp[j][i]=min(dp[j][i],dp[x][i-1]+cost[x+1][j]);
            }
        }
        return dp[s.length()-1][k];
    }
};

在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值