动态规划-字符串处理二题

动态规划刷题篇(二) 👉Example 1(三角形最小路径和) 给定一个三角形 triangle ,找出自顶向下的最小路径和。 每一步只能移动到下一行中相邻的结点上。相邻的结点 在这里指的是 下标 与 上一层结点下标 相同或者等于 上一层结点下标 + 1 的两个结点。也就是说,如果正位于当前行的下标 i ,那么下一步可以移动到下一行的下标 i 或 i + 1 。 示例 1: 输入:triangle = [[2],[3,4],[6,5,7],[4,1,8,3]] 输出:11 解释:如下面简图所示: 2 3 4 ... 阅读详情

第一题来自leetcode: 给一个字母组成的字符串,问最少插入多少字符,使其变成回文串。

这题估计着可以用动态规划解,不过乍看上去,不知如何下手。问题在于如何处理“最少插入字符”。显然最多插入个数是n-1(n是原字符串长度,其中一个做中点),这时原字符串没有任何片断可以作为回文;最少是0,原串已经是回文。

OK,有思路了,我们可以先找到原串中已有的回文字符串片断总长度x,那么 n-x 就是最少插入字符长度。

动态规划,用dp[i][j] 表示对于起始位置为i,长度为j的子字符串中,离散的回文片断总长度。最优子结构如下:


由于子结构是长度减一的子串,那么对于我们的两层遍历,外层应该是长度,里层是起始字符位置。同时注意所有长度为1的片断回文长度为1,作为起点。代码见下:

int turn2palindrome(const string& str){
    int s = str.size();
    int ** dp = new int*[s];
    for(int i=0;i<s;++i){
        dp[i] = new int[s+1]();
    }
    for(int i=0;i<s;++i){
        dp[i][1] = 1; //initialize
    }
    for(int j=2;j<=s;++j){
        for(int i=0;i+j<=s;++i){
            if(str[i] == str[i+j-1]){
                dp[i][j] = 2 + dp[i+1][j-2];
            }else{
                dp[i][j] = max(dp[i+1][j-1], dp[i][j-1]);
            }
        }
    }
    int res = s - dp[0][s];
    /*delete dp*/
    return res;
} 


第二题同样来自leetcode: 一个全由拉丁字母(小写)组成的字符串,可能存在重复字符,问其中最长的无重复字符的子字符串长度。

首先可以估计,它的主要运算是一个时间复杂度为 O(n^2)的过程,对于每一个字符作为起始,考虑每一个新的字符加入后的新子串。问题在于如何确定这个新的字符是否在之前的子串中有过出现。暴力方法中这一步要花 O(n), 这样整个算法需要时间 O(n^3)

我们注意到题目提示字符串全部由26个小写字母组成,如果我们用一个一维数组存有该字母上次出现的位置,就可以在O(1)时间内确定它是否在目前的子串中出现,这样可以将总的时间降到O(n^2)。

动态规划,我们有dp[i][j],表示起点为str[i],长度为j的子串中,最长的无重复字符串长度。最优子结构式如下。

注意对于所有长度为1的子串,dp[i][1] = 1。实现代码如下:

int longestSubstrWithoutDuplicate(const string& str){
    int n = str.size();
    int *alpha = new int[26](); //record latest occurance of alpha char
    for(int i=0;i<26;++i){
        alpha[i] = -1;
    }
    int *pos = new int[n](); //pos[i] means previous occurance of str[i], -1 if not yet
    for(int i=0;i<n;++i){
        int j = str[i]-'a';
        pos[i] = alpha[j];
        alpha[j] = i;
    }
    int **dp = new int*[n]; //dp[i][j] means for substr starting at str[i] with length j, longest substr length without duplicate
    for(int i=0;i<n;++i){
        dp[i] = new int[n+1]();
        dp[i][1] = 1;
    }
    int maxlength=1, start=0;
    for(int j=2;j<=n;++j){
        for(int i=0;i+j<=n;++i){
            if(pos[i+j-1] < i && dp[i][j-1] == j-1){
                dp[i][j] = j;
                if(maxlength < j){
                    maxlength = j;
                    start = i;
                }
            }else{
                dp[i][j] = max(dp[i+1][j-1], dp[i][j-1]);
            }
        }
    }
  /*delete dp[][], pos[] and alpha[]*/  
    printf("method3: result is %s of length %d\n", str.substr(start, maxlength).c_str(), maxlength);
    return maxlength;
}

20131213续,从微博网友得到一个O(n)的算法,很不错,赞一个。

string longeststrwithoutrepeat(const string& str){
    int n = str.size();
    if(n==0)    return str;
    int* pos = new int[26]();
    for(int i=0;i<26;++i){
        pos[i] = -1;
    }
    int* dp = new int[n]();  //length of longest substr without duplicate char that ends at str[i]
    dp[0] = 1;
    pos[str[0] - 'a'] = 0;
    int maxlength = 1, end=0;
    for(int i=1;i<n;++i){
        dp[i] = i - pos[str[i] - 'a'];
        if(dp[i] > dp[i-1] + 1)
            dp[i] = dp[i-1] + 1;
        if(dp[i] == dp[i-1] + 1){
            if(maxlength < dp[i]){
                maxlength = dp[i];
                end = i;
            }
        }
        pos[str[i] - 'a'] = i;
    }
    /* delete dp, pos */
    return str.substr(end-maxlength+1, maxlength);
}

为什么可以把时间降到线性O(n)?我觉得原因在于该问题有其特殊性:

1.必要条件唯一。对于尾字符str[i],距离其上次出现的长度 i - pos[i]必定大于等于dp[i],即 i - pos[i]成为dp[i]的上限。

2. 充分条件唯一。当str[i] != str[i-1]时,dp[i]最多等于dp[i-1] + 1, dp[i]仅仅依赖于dp[i-1]。

反思:

再反过来重新思考其他问题,比如前文的”最少插入字符“。对于离散回文片断长度的查找,问题是在其子结构式中,关系比较的式子是dp[j] ? dp[i], 这里的i是子字符串的起始,它是由末尾 j 和长度 l 两个正交的参数共同确定的。这使得我们必须使用二维数组dp[i][j]作为动态规划的临时结构,从而算法的时间复杂度也就无法再降低了。

小结:

对于字符串处理的最大/最小问题,多数时候O(n^2)是最佳性能,但不排除有些情况能够降到线性O(n)。

动态规划题:把一个字符串变为回文串 版权所有。所有权利保留。 欢迎转载,转载时请注明出处: http://blog.youkuaiyun.com/xiaofei_it/article/details/17172891 把一个字符串变成回文串,最少要添加几个字符? 动态规划解: f(i,j)表示s[i..j]变为回文串需要添加的最少字符数。 f(i,j)=0 if i>=j f(i,j)=f[i+1][j-1] 阅读详情

相关推荐

【动态规划】【字符串】87扰乱字符串

使用下面描述的算法可以扰乱字符串 s 得到字符串 t : 如果字符串的长度为 1 ,算法停止 如果字符串的长度 > 1 ,执行下述步骤: 在一个随机下标处将字符串分割成两个非空的子字符串。即,如果已知字符串 s ,则可以将其分成两个子字符串 x 和 y ,且满足 s = x + y 。 随机 决定是要「交换两个子字符串」还是要「保持这两个子字符串的顺序不变」。即,在执行这一步骤之后,s 可能是 s = x + y 或者 s = y + x 。 在 x 和 y 这两个子字符串上继续从步骤 1 开始递归执行此算

闻缺陷则喜何志丹 5119

笔记——动态规划字符串类题目小结

题目1:最大递增子序列    我的代码 给定数组arr,返回arr最长递增子序列长度。比如arr=[2,1,5,3,6,4,8,9,7],最长递增子序列为[1,3,4,8,9],所以返回5 题目2:最长公共子序列    我的代码 给定两个字符串,求解这两个字符串的最长公共子序列(Longest Common Sequence)。 比如字符串1:BDCABA;字符串2:ABCBDAB 则这...

皮蛋瘦肉没有肉 611

【动态规划】【字符串】【行程码】1531. 压缩字符串

行程长度编码 是一种常用的字符串压缩方法,它将连续的相同字符(重复 2 次或更多次)替换为字符和表示字符计数的数字(行程长度)。例如,用此方法压缩字符串 "aabccc" ,将 "aa" 替换为 "a2" ,"ccc" 替换为` "c3" 。因此压缩后的字符串变为 "a2bc3" 。 注意,本问题中,压缩时没有在单个字符后附加计数 '1' 。 给你一个字符串 s 和一个整数 k 。你需要从字符串 s 中删除最多 k 个字符,以使 s 的行程长度编码长度最小。 请你返回删除最多 k 个字符后,s 行程长度编码

闻缺陷则喜何志丹 3361

搜集动态规划处理字符串

最长公共子序列求解:递归与动态规划方法  在做OJ题目的时候,经常会用到字符串的处理。例如,比较二个字符串相似度。这篇文章介绍一下求两个字符串的最长公共子序列。  一个字符串的子序列,是指从该字符串中去掉任意多个字符后剩下的字符在不改变顺序的情况下组成的新字符串。  最长公共子序列,是指多个字符串可具有的长度最大的公共的子序列。  (1)递归方法求最长公共子序列的长度    1)设有字符串a[0....

winggyn的专栏 545

在windows上,在WSL 2(windows subsystem linux) 里一步步安装vLLM

本文介绍了在Windows系统上通过WSL2配置GPU加速的AI开发环境的完整流程。主要包括四个步骤: 1)安装WSL2并配置Ubuntu环境; 2)安装NVIDIA驱动和CUDA工具包; 3)搭建Python虚拟环境并安装vLLM; 4)验证环境并启动AI模型服务。

2601_96126911的博客 421

风光储互补微电网在偏远地区的应用实践:从建模到仿真全解析

本文深入解析了风光储互补微电网在偏远地区的应用实践,从系统设计到仿真建模全流程。通过Simulink等工具进行动态仿真,验证了系统在多种工况下的可靠性,并结合实际案例展示了其显著的经济和环保效益。文章为从业者提供了从技术路径到实施优化的全面指导。

weixin_29047545的博客 270

一招解决4道leetcode hard题,动态规划在字符串匹配问题中的应用

全文共2869个字,6张图,预计阅读时间15分钟。在做leetcode的时候,遇到hard题大家往往都觉得头疼,但其实,掌握方法,举一反三,hard题有时候我们也能想到好...

leadai的博客 953

避坑指南:QCustomPlot鼠标事件冲突解决方案(左键拖动vs右键框选)

本文深入解析QCustomPlot在QT框架下的高级交互实现,重点解决左键拖动与右键框选的冲突问题。通过自定义事件处理和QRubberBand技术,提供了一套完整的无冲突交互方案,帮助开发者优化数据可视化应用的用户体验。

moss5的博客 660

Leetcode 题解 - 动态规划-字符串编辑(1):删除两个字符串的字符使它们相等

[LeetCode] Delete Operation for Two Strings 两个字符串的删除操作 求最大子序列的长度, 然后总长度减去 2*子序列长度 两种情形求子序列 dp[i][j] = dp[i-1][j-1] + 1 好理解吧 就是当前两个字符相等 两个字符不相等的时候就是 dp[i][j]= Math.max(dp[i-1][j], dp[i][j-1]) i个字符和j...

qq_40320556的博客 915

数据预处理的分箱操作

数据分箱 介绍 我们在建立模型前,一般需要对特征变量进行离散化,特征离散化后,模型会更稳定,降低模型过拟合的风险。尤其是采用 logsitic 建立评分卡模型时,必须对连续变量进行离散化。而特征离散化处理通常采用的就是分箱法,数据分箱(也称为离散分箱或分段)是一种数据预处理技术,用于减少次要观察误差的影响,提高泛化性。 数据分箱又分为有监督分箱和无监督分箱,是否使用标签进行离散化(分箱)决定了有监督还是无监督的离散化方法。 知识点 无监督分箱 split 分箱 merge 分箱 无监督分箱 这里为了

随笔记 5334

【推荐100个unity插件】unity易于使用模块化设计的天空、体积云和天气系统——Enviro 3

Enviro 3是一款功能强大的Unity天空与天气系统插件,提供动态天空、体积云、天气模拟等丰富功能。安装时需将预制体拖入场景并配置主相机,URP支持需激活深度纹理和添加渲染特性。模块化设计允许自由添加/移除时间、光照、雾效等模块,并通过API控制参数。推荐配合色调映射(如ACES模式)获得最佳视觉效果。插件支持季节、温湿度模拟及闪电风暴等特效,适用于需要逼真环境渲染的Unity项目。

向宇的博客,专注php/web全栈 unity游戏开发,欢迎大家评论纠错 2094

最长公共子序列

给定两个字符串 text1 和 text2,返回这两个字符串的最长公共子序列的长度。 一个字符串的 子序列 是指这样一个新的字符串:它是由原字符串在不改变字符的相对顺序的情况下删除某些字符(也可以不删除任何字符)后组成的新字符串。 例如,"ace" 是 "abcde" 的子序列,但 "aec" 不是 "abcde" 的子序列。两个字符串的「公共子序列」是这两个字符串所共同拥有的子序列。 若这两个字符串没有公共子序列,则返回 0。 示例 1: 输入:text1 = "abcde", text2 .

weixin_44895315的博客 336

【小白深度教程 1.8】手把手教你使用 Depth Anything V2 估计单目深度,并映射到 3D 点云(含 Python 代码)

我们尝试使用单目深度估计技术(Depth Anything V2),来进行准确的双目深度估计,并将场景转换成 3D 点云,Python 代码在最后。

2401_87064292的博客 5090

LeetCode 热题 100 - 动态规划 - 最长回文子串 - javascript

给你一个字符串s,找到s中最长的 回文 子串。

weixin_47218107的博客 539

Calibre 3Dstack Flow Example(5-2)

本文详细介绍了Calibre3DSTACK工具在3D-IC设计验证中的应用。主要内容包括:1)连通性检查(LVS)规则编写,重点说明connected命令的使用方法和多文本标签处理;2)设计规则检查(DRC)实现,涵盖层间距检查和焊盘重叠检查;3)系统网表生成器操作流程,从芯片导入到网连通性定义;4)两种规则文件语法(扩展语法和传统语法)的编写示例;5)验证报告文件格式解析。通过具体案例演示了如何建立完整的3D-IC验证流程,包括芯片定义、装配操作、电气连接验证和物理规则检查等关键步骤,为3D-IC设计验证

u013620135的博客 2336

解锁RK3588多屏异显:MIPI+HDMI+EDP混合输出全攻略

本文详细介绍了RK3588处理器在MIPI+HDMI+EDP混合输出配置中的技术实现与应用。作为一款高性能处理器,RK3588凭借其强大的图形处理能力,支持多屏异显功能,可满足智能安防、工业控制等领域的多屏显示需求。文章从硬件连接、设备树配置、内核驱动设置到显示参数调整,系统阐述了配置流程,并针对信号不稳定、显示模式不匹配等常见问题提供了解决方案。通过智能安防监控案例,展示了该技术在提高监控效率方面的实际应用价值。随着技术进步,RK3588多屏异显技术将在更多领域发挥重要作用,为开发者提供灵活多样的显示方案

远程部署调试 运行安装 项目调试 二次开发 项目技术新 持续迭代 部分源码免费分享 2433

【Leetcode子序列-编辑距离】115. 不同的子序列(一个字符串可以删除) 583. 两个字符串的删除操作(两个字符串都可以删除) 72. 编辑距离

文章目录Leetcode1151.问题描述2.解决方案a.dp的定义多看几遍和之前的公共子序列有所不同,dp[i][j]:以i-1结尾的s子序列中出现以j-1结尾的t的个数为dp[i][j],注意全部都是结尾而不是范围b.递推就和之前不太一样了,之前按道理dp定义为结尾的话只有一种状态来源,但是这道题特殊性,虽然s[i-1]==t[j-1]但是也可以匹配也可以不匹配c.初始化就很烦了d.遍历顺序就正常1到len就好e.经常会出现相加溢出的情况,直接把dp定义为无符号数64位表示的正数相当大,一般不会溢出了

AloneYue优快云 544

RU DOS版、EFI版32bit/64bit BIOS常用工具

DOS版、EFI版的RU工具,可用来查看IO、MEM、PCI、SMBIOS等资源。亲测在EFI SHELL下可用。

面试经典 150 题:121,125

【代码】面试经典 150 题:121,125。

CH3CH2CH4的博客 514

C# WinForm 基于DirectShow.dll编写的程序,可边预览边保存视频,音频和图片

基于微软的DirectShow.dll的二次开发1.自动识别连接的摄像头跟麦克风且可以对其进行选择(默认选中第一个)2.可录制wmv和avi两种格式的视频并且都带有音频,avi可以录制的分辨率和帧数进行选择,wmv默认进行了淸晰度优化如不喜欢可去除代码中有相关提示3.可在预览点开之后进行拍照,也可边录制视频边拍照4.添加了视频和音频的压缩功能(酌情使用)这次二次开发发现C#对DirectShow的相关信息太少,这次做完也不敢藏私共享出来,还望大家指正

怀旧版电脑GBC模拟器

再现原版GBC掌机的界面,电脑运行连游戏界面都一样大小,很怀旧,很真实,(英文版)强烈推荐,很小的文件,很难才找到的。

力扣刷题记录(c++)03

这道题的提示其实已经很明显了,假设一个坐标为[x, y],那么ans[x][y] = min(ans[x-1][y],ans[x-1][y-1],ans[x-1][y+1])。假设matrix大小为n*m的,我们将dp数组设计为(n+1)*(m+2)的,除了第一行初始化为0,其余全部初始化为INT_MAX,可以避免我们对边界数据的特殊化处理。可以从第一行中的任何元素开始,并从每一行中选择一个元素。在下一行选择的元素和当前行所选元素最多相隔一列(即位于正下方或者沿对角线向左或者向右的第一个元素)。

2301_80079840的博客 646

VB摄像头监控

该VB模块可对摄像头捕获的画面进行录像等,可在创建的窗口进行控制

Microsoft刷题记录

PASS区 PASS但非最优 非PASS区

bob的博客 802

代码随想录算法训练营第五十五天|583.两个字符串的删除操作|72. 编辑距离

代码随想录算法训练营第五十五天|583.两个字符串的删除操作|72. 编辑距离

saonantabusao的博客 170

【LeetCode刷题笔记】动态规划(二)

LeetCode刷题笔记之动态规划篇(二)。

川峰的博客 1730

动态规划与字符串处理

整除子集是指子集中的每一对 (i, j) 满足 nums[i] % nums[j] == 0 或 nums[j] % nums[i] == 0。给定一个字符串 s,计算该字符串的分数,定义为相邻字符的 ASCII 码差值的绝对值之和。动态规划:我们维护一个 f 数组,表示以 nums[i] 作为结尾的最大整除子集的大小,并通过 g 数组记录每个元素的前驱索引。回溯:遍历 f 数组,找到最大的子集长度,并通过 g 数组回溯得到子集的元素。时间复杂度:O(n),其中 n 是字符串的长度,遍历一次字符串即可。

qq_17405059的博客 789

字符串处理中的动态规划

今天面试美团,一面挂,出了一道数组处理题目,完全想不到是用动态规划的方式解决。这里开始总结一下这类题目,即用动态规划的方式处理字符串类型题目。

weixin_42382512的博客 673

leetcode刷题(javaScript)——动态规划相关场景题总结

动态规划在 JavaScript 刷题中有一定的难度,但也是非常常见和重要的算法思想。动态规划通常适用于需要求解最优解、最大值、最小值等问题的场景,可以将复杂问题拆分成子问题,通过存储子问题的解来避免重复计算,从而提高效率。理解问题的状态转移方程: 动态规划的核心是找到问题的状态转移方程,即如何从子问题的解推导出更大规模问题的解。理解问题的状态转移方程是解决动态规划问题的关键。定义合适的状态数组: 在解决动态规划问题时,通常需要定义一个状态数组来存储子问题的解。确保状态数组的定义清晰

涵盖了计算机专业基础知识、数学建模相关实践、复杂网络论文研究、LeetCode算法刷题经验、C语言开发经验、前端Vue、React框架开发实战相关知识 1695

【二维动态规划:交错字符串】

交错字符串

博客网站地址: https://arsenova.xyz 我会将优快云上的博客重修一部分迁移到网站上。 文章会做同步更新,但我不会在这个糟糕的平台多待1秒。下面是我要说的话,save your time. keep going 1755
上一篇: 两有序数组两两之和的最小k个值, 最小堆解法之完整版
下一篇: 动态规划-有向无回路图中两点间最远距离
teaspring
博客等级 码龄19年 350粉丝 24原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

抵扣说明:

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

余额充值