c语言编程题 回文串,力扣132. 分割回文串 II-C语言实现-困难题

力扣132. 分割回文串 II-C语言实现-困难题

题目(真心不会)

传送门

文本

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

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

示例 1:

输入:s = "aab"

输出:1

解释:只需一次分割就可将 s 分割成 ["aa","b"] 这样两个回文子串。

示例 2:

输入:s = "a"

输出:0

示例 3:

输入:s = "ab"

输出:1

提示:

1 = s.length = 2000

s 仅由小写英文字母组成

来源:力扣(LeetCode)

模板

int minCut(char * s){

}

解题

分析

设 f[i]f[i]f[i] 表示字符串的前缀 s[0..i]s[0..i]s[0..i] 的最少分割次数。要想得出 f[i]f[i]f[i] 的值,我们可以考虑枚举 s[0..i]s[0..i]s[0..i] 分割出的最后一个回文串,这样我们就可以写出状态转移方程:

f[i]=min?0≤ji{f[j]}+1,其中 s[j+1..i] 是一个回文串f[i] = \min_{0 \leq j i} { f[j] } + 1, \quad 其中 ~ s[j+1..i] ~是一个回文串 f[i]=0≤jimin?{f[j]}+1,其中 s[j+1..i] 是一个回文串

即我们枚举最后一个回文串的起始位置 j+1j+1j+1,保证 s[j+1..i]s[j+1..i]s[j+1..i] 是一个回文串,那么 f[i]f[i]f[i] 就可以从 f[j]f[j]f[j] 转移而来,附加 111 次额外的分割次数。

注意到上面的状态转移方程中,我们还少考虑了一种情况,即 s[0..i]s[0..i]s[0..i] 本身就是一个回文串。此时其不需要进行任何分割,即:

f[i]=0f[i] = 0 f[i]=0

那么我们如何知道 s[j+1..i]s[j+1..i]s[j+1..i] 或者 s[0..i]s[0..i]s[0..i] 是否为回文串呢我们可以使用与「131. 分割回文串的官方题解」中相同的预处理方法,将字符串 sss 的每个子串是否为回文串预先计算出来,即:

设 g(i,j)g(i, j)g(i,j) 表示 s[i..j]s[i..j]s[i..j] 是否为回文串,那么有状态转移方程:

g(i,j)={True,i≥jg(i+1,j?1)∧(s[i]=s[j]),otherwiseg(i, j) = \begin{cases} \texttt{True}, \quad i \geq j \ g(i+1,j-1) \wedge (s[i]=s[j]), \quad \text{otherwise} \end{cases} g(i,j)={True,g(i+1,j?1)∧(s[i]=s[j]),?i≥jotherwise?

其中 ∧\wedge∧ 表示逻辑与运算,即 s[i..j]s[i..j]s[i..j] 为回文串,当且仅当其为空串(ijijij),其长度为 111(i=ji=ji=j),或者首尾字符相同且 s[i+1..j?1]s[i+1..j-1]s[i+1..j?1] 为回文串。

这样一来,我们只需要 O(1)O(1)O(1) 的时间就可以判断任意 s[i..j]s[i..j]s[i..j] 是否为回文串了。通过动态规划计算出所有的 fff 值之后,最终的答案即为 f[n?1]f[n-1]f[n?1],其中 nnn 是字符串 sss 的长度。

作者:LeetCode-Solution

链接:https://leetcode-cn.com/problems/palindrome-partitioning-ii/solution/fen-ge-hui-wen-chuan-ii-by-leetcode-solu-norx/

来源:力扣(LeetCode)

著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

完整源码

传送门

int minCut(char* s) {

int n = strlen(s);

bool g[n][n];

memset(g, 1, sizeof(g));

for (int i = n - 1; i = 0; --i) {

for (int j = i + 1; j n; ++j) {

g[i][j] = (s[i] == s[j]) g[i + 1][j - 1];

}

}

int f[n];

for (int i = 0; i n; ++i) {

f[i] = INT_MAX;

}

for (int i = 0; i n; ++i) {

if (g[0][i]) {

f[i] = 0;

} else {

for (int j = 0; j i; ++j) {

if (g[j + 1][i]) {

f[i] = fmin(f[i], f[j] + 1);

}

}

}

}

return f[n - 1];

}

运行结果

力扣132. 分割回文串 II-C语言实现-困难题 相关文章

【题解】力扣765. 情侣牵手

765. 情侣牵手 题目来源 765. 情侣牵手 思路 如果一对情侣恰好坐在了一起,并且坐在了成组的座位上,其中一个下标一定是偶数,另一个一定是奇数,并且「偶数的值 + 1 = 奇数的值」。例如编号数对 [2, 3] 、 [9, 8] ,这些数对的特点是除以 2(下取整)得到的

二叉树的右视图和先重建二叉树,再打印二叉树的右视图(力扣199题、NC136题)

199.二叉树的右视图 ?给定一棵二叉树,想象自己站在它的右侧,按照从顶部到底部的顺序,返回从右侧所能看到的节点值。 输入:[1,2,3,null,5,null,4]输出:[1, 3, 4]解释: 1 --- / \2 3 --- \ \ 5 4 --- 利用层次遍历寻找二叉树中的右视图(层次遍历,一次外循

07. 重建二叉树

题目 力扣-剑指 Offer 07. 重建二叉树 输入某二叉树的前序遍历和中序遍历的结果,请重建该二叉树。假设输入的前序遍历和中序遍历的结果中都不含重复的数字。 例如,给出前序遍历 preorder = [3,9,20,15,7]中序遍历 inorder = [9,3,15,20,7]返回如下的二叉树:

二分图基础

概念 二分图定义 : 设G=(V,E)是一个无向图,如果顶点V可分割为两个互不相交的子集(A,B),并且图中的每条边(i,j)所关联的两个顶点i和j分别属于这两个不同的顶点集(i in A,j in B),则称图G为一个二分图。 二分图概念 : 当且仅当图中不含奇数环。 奇数环

剑指 Offer 06. 从尾到头打印链表

题目 力扣-剑指 Offer 05. 替换空格 请实现一个函数,把字符串 s 中的每个空格替换成%20。 示例 1:输入:s = We are happy.输出:We%20are%20happy. 限制:0 = s 的长度 = 10000 题解 该题难度为简单。 解法一:两个for循环 1,先声明两个整型数组; 2,第一

webpack高级概念,CSS文件的代码分割 与压缩(系列八)

我们之前写的css文件都会被打包进js文件中,要想把css单独打包成一个css文件该怎么做呢 这个时候就需要用到 MiniCssExtractPlugin 开发环境用不到这个功能(因为这个东西不支持热模块更新,样式更改自动替换,不用刷新页面), 一般都是用在生产环境中 。 安

刷题-力扣-503

503. 下一个更大元素 II 题目链接 来源:力扣(LeetCode) 链接:https://leetcode-cn.com/problems/next-greater-element-ii/ 著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。 题目描述 给定一个循环数组(最后一个元素的下一个元素

力扣503. 下一个更大元素 II-C语言实现-中等难度题

题目 传送门 文本 给定一个循环数组(最后一个元素的下一个元素是数组的第一个元素),输出每个元素的下一个更大元素。数字 x 的下一个更大的元素是按数组遍历顺序,这个数字之后的第一个比它更大的数,这意味着你应该循环地搜索它的下一个更大的数。如果不

刷题-力扣-232

232. 用栈实现队列 题目链接 来源:力扣(LeetCode) 链接:https://leetcode-cn.com/problems/implement-queue-using-stacks/ 著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。 题目描述 请你仅使用两个栈实现先入先出队列。队列应当

剑指 Offer 07. 重建二叉树

题目 力扣-剑指 Offer 07. 重建二叉树 输入某二叉树的前序遍历和中序遍历的结果,请重建该二叉树。假设输入的前序遍历和中序遍历的结果中都不含重复的数字。 例如,给出前序遍历 preorder =[3,9,20,15,7]中序遍历 inorder = [9,3,15,20,7]返回如下的二叉树:

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值