字符串上的简单动态规划

因为数据结构快学串了,以前又做过一些字符串dp的题,今天突然就想把它们写在一起吧。

 

直接开始

问题1:给两个字符串,求最长公共子串

问题2:给两个字符串,求最长公共子序列

问题3:给一个字符串,求最长回文子串

问题4:给一个字符串,求最长回文子序列

问题5:给一个字符串,求将这个字符串变为回文串需要插入的最少字符个数。

问题6:最小编辑代价

问题7:判断交错组成

问题8:给一个字符串,求最长相同前后缀

问题9:给串a和b,判断b是否在a中出现,若出现输出第一次出现的位置。

问题1:给两个字符串,求最长公共子串

串和序列的区别之前提到过,串连续,序列可以不连续

如果连续那就比较好想了,定义DP(i,j)的含义是两个串分别以下标i和j结尾最长的公共子串长度。

如果a[i]=b[j],那DP(i,j)=DP(i-1,j-1)+1,如果DP(i-1,j-1)=0,还是同样的操作,仅仅是之前不能构成而已,那i和j结尾的最长一定是1了。

如果a[i]!=b[j],DP(i,j)=0,因为定义是以i和j结尾,一定不存在这样的相同子串。

初始化:先打第一行和第一列,相同为1,不同为0即可。

问题2:给两个字符串,求最长公共子序列

举例:

S1=“ABCBDAB.”

S2=“BABCBD.”

可以看出他们的最长公共子序列有ABCB,ABCD ,BCBD等,长度为4.

Dp(i,j)表示S的前i位与T的前j位的最长公共子串长度。

如果a[i]=b[j],那DP(i,j)=DP(i-1,j-1)+1

否则,DP(i,j)=max(DP(i-1,j),DP(i,j-1))

仔细体会,手模拟几个就懂了。第一次想可能没那么容易

拓展:三个字符串:纯dp做

注:多个字符串要其他做法,以后数据结构学到串了或者树了再写。

 

问题3:给一个字符串,求最长回文子串

马拉车算法,我确实觉得也是动态规划思想,跳转看详细介绍吧

https://blog.csdn.net/hebtu666/article/details/79822584

 

问题4:给一个字符串,求最长回文子序列

对于任意字符串,如果头尾字符相同,那么字符串的最长子序列等于去掉首尾的字符串的最长子序列加上首尾;如果首尾字符不同,则最长子序列等于去掉头的字符串的最长子序列和去掉尾的字符串的最长子序列的较大者。

因此动态规划的状态转移方程为:

设字符串为str,长度为n,p[i][j]表示第i到第j个字符间的子序列的个数(i<=j),则:

状态初始条件:dp[i][i]=1 (i=0:n-1)

状态转移方程:dp[i][j]=dp[i+1][j-1] + 2  if(str[i]==str[j])

                   dp[i][j]=max(dp[i+1][j],dp[i][j-1])  if (str[i]!=str[j])

计算dp[i][j]时需要计算dp[i+1][*]或dp[*][j-1],因此i应该从大到小,即递减;j应该从小到大,即递增。注意必须满足i<=j的条件。

问题5:给一个字符串,求将这个字符串变为回文串需要插入的最少字符个数。

举例:

ab3bd

只需变为adb3bda即可,在前面插入d,在后面插入a;

思路:

设dp(i,j)为将Ai..Aj变为回文串的最小代价,如果a[i]=a[j],那不用说了,肯定是dp(i,j)=dp(i+1,j-1),如果不相同,在前面或者后面插入一个字符,即dp(i,j)=min(dp(i,j-1),dp(i+1,j))+1

注意dp顺序:

for i:=n downto 1

    for j:=i+1 to n

 

 

另一种思路:

将原串与原串的倒序做一次最长公共子序列,用原串长度减去最长公共子序列长度,即为需要插入字符的个数。逻辑很好想,不过多介绍

 

问题6:最小编辑代价

这个解释有点麻烦,思路分的比较多,是个值得好好思考一下的题。

[题目]

 给定两个字符串str1 和str2,再给定三个整数ic、dc 和rc,分别代表插入、删除和替换一个字符的代价,返回将str1编辑成str2的最小代价。

(举例]

      str1="abc",str2="adc", ic=5,  dc=3,  rc=2。

      从"abc"编辑成"adc",把b'替换成'd是代价最小的,所以返回2。str1="abc",str2="adc", ic=5,  dc=3,  rc=100。

      从"abc"编辑成"adc",先删除"b', 然后插入d是代价最小的,所以返回8。str1="abc",str2="abc", ic=5,  dc=3,  rc=2。

      不用编辑了,本来就是一样的字符串,所以返回0。

 

思路:定义dp(i,j)为str1下标i之前编辑到str2下标j之前需要的最小代价。

Dp[0][0]=0,空到空,不用改变。

矩阵dp第一列即dp[..M-1][0]。dp[i][0]表 示str1[0..-1]编辑成空串的最小代价,亳无疑问,是把str1[..i1]所有的字符删掉的代价,所以dp[i][0]=dc*i。

.矩阵dp第一行即dp[0][..N-1]。 dp[0][j]表示空串编辑成str2[O.j-1]的最小代价,亳无疑问,是在空串里插入str2[0.j-1]所有字符的代价,所以dp[0][]=ic*j。

 

其他位置按照从左到右,再从上到下来计算,dp[i][j]的值只可能来自以下四种情况。

      str1[0.i-1]可以先编辑成str1[..i-2], 也就是删除字符str1[i-1], 然后由str1[0.i-2]编辑成str2[0.j-1], dp[i-1][i]表 示str1[0.i-2]编辑成 str2[0.j-1]的 最小代价,那么dp[i][j]可能等于dc+dp[i-1][j]

      str1[0.i-1]可以先编辑成str2[0.j-2], 然后将str2[0.j-2]插入字符str2[j-1], 编辑成str2[0.j-1],dp[i][j-1]表 示str1[..i-1]编 辑成str2[0.j-2]的最小代价, 那么dp[i][j]可能等于dp[i][j-1]+ic。

      如果str1[i-1]!=str2[j-1]。先把str1[0.i-1]中str1[..i-2]的 部分变成str2[0.j-2], 然后把字符str1[i-1]替换成str2[-1], 这样str1[..i-1]就编辑成str2[0.j1]了 。dp[i-1][j-1]表示str1[..i-2]编辑成str2[..i-2]的最小代价,那么dp[i][j]可 能等于dp[i-1]j-1]+rc.

如果str1[i-1]==str2[j-1]. 先把str1[0..i-1]中 str1[0..i-2]的 部分变成str2[0.j-2],  因为此时字符str1[i-1]等 于str2[j-1], 所以str1[0.i-1]已 经编辑成str2[0.j-1]了 。dp[i-1][j-1]表示str1[0i-2]编辑 成str2[..i-2]的 最小代价,那么dp[]ij]可能等于dp[i-1][j-1]

 

问题7:判断交错组成

给定三个字符串strl str2和aim,如果aim包含且仅包含来自str1 和str2的所有字符,而且在aim中属于str1的字符之间保持原来在str1中的顺序,属于str2的字符之间保持原来在str2中的顺序,那么称aim是str1和str2的交错组成。实现-一个函数,判断aim是否是str1和str2交错组成。

思路:做这个题一开始脑子没开窍,老想三维,表示str1的前i个和str2的前j个,组成aim的k个,但其实k只能是i+j,所以,dp[i][j]为str1的前i个和str2的前j个能否组成aim(i+j)。

那就简单了,要么放i要么放j,都不行就是0,有一个可以就是1.

问题8:给一个字符串,求最长相同前后缀,前缀不包括最后一个字符,后缀不包括第一个字符。

注意看kmp的next数组思想。先看下面的再看这个

https://blog.csdn.net/hebtu666/article/details/82492803

问题9:给串a和b,判断b是否在a中出现,若出现输出第一次出现的位置。

8和9看kmp详解:https://blog.csdn.net/hebtu666/article/details/79822446

 

 

 

 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/445616.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

线段树简单实现

首先&#xff0c;线段树是一棵满二叉树。&#xff08;每个节点要么有两个孩子&#xff0c;要么是深度相同的叶子节点&#xff09; 每个节点维护某个区间&#xff0c;根维护所有的。 如图&#xff0c;区间是二分父的区间。 当有n个元素&#xff0c;初始化需要o(n)时间&#xf…

树状数组实现

树状数组能够完成如下操作&#xff1a; 给一个序列a0-an 计算前i项和 对某个值加x 时间o(logn) 注意&#xff1a;有人觉得前缀和就行了&#xff0c;但是你还要维护啊&#xff0c;改变某个值&#xff0c;一个一个改变前缀和就是o(n)了。 线段树树状数组的题就是这样&#x…

数据结构课上笔记2

今天继续说明了一些基本概念&#xff0c;讲解了时间空间复杂度。 &#xff08;对于概念的掌握也很重要&#xff09; 元素之间的关系在计算机中有两种表示方法&#xff1a;顺序映像和非顺序映像&#xff0c;由此得到两种不同的储存结构&#xff1a; 顺序存储结构和链式存储结构…

双端单调队列

上次我们介绍了单调栈结构https://blog.csdn.net/hebtu666/article/details/82717317 这次介绍一种新的数据结构&#xff1a;双端队列&#xff1a;双端队列是指允许两端都可以进行入队和出队操作的队列&#xff0c;其元素的逻辑结构仍是线性结构。将队列的两端分别称为前端和后…

KMP子字符串匹配算法学习笔记

文章目录学习资源什么是KMP什么是前缀表为什么一定要用前缀表如何计算前缀表前缀表有什么问题使用next数组来匹配放码过来构造next数组一、初始化二、处理前后缀不相同的情况三、处理前后缀相同的情况使用next数组来做匹配代码总览测试代码时间复杂度分析学习资源 字符串&…

数组实现队列

数组实现队列结构&#xff1a; 相对栈结构要难搞一些&#xff0c;队列的先进先出的&#xff0c;需要一个数组和三个变量&#xff0c;size记录已经进来了多少个元素&#xff0c;不需要其它萌新看不懂的知识。 触底反弹&#xff0c;头尾追逐的感觉。 循环使用数组。 具体解释…

栈/队列 互相模拟实现

用两个栈来实现一个队列&#xff0c;完成队列的Push和Pop操作。 队列中的元素为int类型。 思路&#xff1a;大概这么想&#xff1a;用一个辅助栈把进第一个栈的元素倒一下就好了。 比如进栈1&#xff0c;2&#xff0c;3&#xff0c;4&#xff0c;5 第一个栈&#xff1a; 5 …

数据结构课上笔记3

这节课介绍了线性表结构和顺序表示的一部分内容。 操作太多&#xff0c;而且书上有&#xff0c;就不一一介绍分析了。 线性表定义&#xff1a;n个数据元素的有限序列。 特点&#xff1a; 存在唯一一个称作“第一个”的元素。存在唯一一个称作“最后一个”的元素除最后一个元…

内存分区

之前一直比较懵&#xff0c;想想还是单独写一个短篇来记录吧 一般内存主要分为&#xff1a;代码区、常量区、静态区&#xff08;全局区&#xff09;、堆区、栈区这几个区域。 代码区&#xff1a;存放程序的代码&#xff0c;即CPU执行的机器指令&#xff0c;并且是只读的。 常…

栈的排序

一个栈中元素的类型为整型&#xff0c;现在想将该栈从顶到底按从大到小的顺序排序&#xff0c;只许申请一个栈。除此之外&#xff0c;可以申请新的变量&#xff0c;但是不能申请额外的数据结构&#xff0c;如何完成排序&#xff1f; 思路&#xff1a; 将要排序的栈记为stack,申…

双链表实现

以前写的不带头的单链表实现&#xff0c;当时也啥也没学&#xff0c;好多东西不知道&#xff0c;加上一心想压缩代码&#xff0c;减少情况&#xff0c;所以写得不太好。 请教了老师&#xff0c;首先是命名问题和代码紧凑性等的改进。还有可读性方面的改进&#xff0c;多写了一…

数据结构作业1 讲解和拓展

原题来自雪梨教育 http://www.edu2act.net/task/list/checked/ 题后给出讲解和扩展 任务1_1 比较下列算法的时间复杂度 任务描述&#xff1a; 下面给出4个算法&#xff0c;请分析下列各算法的时间复杂度&#xff0c;请写清楚题号&#xff0c;并将每个小题的分析过程写出来&…

KMP+DP1

Description 求一个字符串的所有前缀在串中出现的次数之和 Input 多组用例&#xff0c;每组用例占一行为一个长度不超过100000的字符串&#xff0c;以文件尾结束输入 Output 对于每组用例&#xff0c;输出该字符串的所有前缀在串中出现的次数之和&#xff0c;结果模256 Samp…

数据结构课上笔记5

介绍了链表和基本操作 用一组物理位置任意的存储单元来存放线性表的数据元素。 这组存储单元既可以是连续的&#xff0c;也可以是不连续的&#xff0c;甚至是零散分布在内存中的任意位置上的。因此&#xff0c;链表中元素的逻辑次序和 物理次序不一定相同。 定义&#xff1a; …

并查集入门三连:HDU1213 POJ1611 POJ2236

HDU1213 http://acm.hdu.edu.cn/showproblem.php?pid1213 问题描述 今天是伊格纳修斯的生日。他邀请了很多朋友。现在是晚餐时间。伊格纳修斯想知道他至少需要多少桌子。你必须注意到并非所有的朋友都互相认识&#xff0c;而且所有的朋友都不想和陌生人呆在一起。 这个问题…

Java设计模式(2 / 23):观察者模式

定义 观察者&#xff08;Observer&#xff09;模式定义了对象之间的一对多依赖&#xff0c;这样一来&#xff0c;当一个对象改变状态时&#xff0c;它的所有依赖者都会收到通知并自动更新。 OO设计原则&#xff1a;为了交互对象之间的松耦合设计而努力。 案例&#xff1a;气…

二叉树概述

各种实现和应用以后放链接 一、二叉树的基本概念 二叉树&#xff1a;二叉树是每个节点最多有两个子树的树结构。 根节点&#xff1a;一棵树最上面的节点称为根节点。 父节点、子节点&#xff1a;如果一个节点下面连接多个节点&#xff0c;那么该节点称为父节点&#xff0c;它…

Java设计模式(1 / 23):策略模式

定义 策略&#xff08;Strategy&#xff09;模式定义了算法族&#xff0c;分别封装起来&#xff0c;让它们之间可以互相替换 &#xff0c;此模式让算法的变化独立于使用算法的客户。 案例&#xff1a;模拟鸭子应用 一开始 新需求&#xff1a;模拟程序需要会飞的鸭子 在父类新…

Java设计模式(3 / 23):装饰者模式

文章目录定义案例1&#xff1a;三点几啦首次尝试再次尝试设计原则&#xff1a;类应该对扩展开放&#xff0c;对修改关闭尝用装饰者模式装饰者模式特征本例的类图放码过来饮料类HouseBlendDarkRoastEspressoDecaf调料装饰类MilkMochaSoyWhip运行测试类案例2&#xff1a;编写自己…

c语言知识体系

原文&#xff1a;https://blog.csdn.net/lf_2016/article/details/80126296#comments