当前位置:网站首页>动态规划:最长回文子串和子序列
动态规划:最长回文子串和子序列
2022-07-03 03:28:00 【我家大宝最可爱】
1. 回文子串
回文串就是正着读和反着读都一样的字符串,例如aba,aabb等,给定一个字符串,求最长回文子串。注意子串是指连续的
1.1左右扩展
左右扩展的思想很有意思,如果一个问题用到了左右扩展的想法,那么久直接定以两个范围l,r,这样就可以避免奇偶问题了
一种非常直接的想法就是从某个字符开始,向两边开始搜索,然后匹配字符是否相等
| <—向左搜索 | 某个字符 | 向右搜索—> | |
|---|---|---|---|
| 字符串 | a | b | a |
| 搜索边界 | l | r |
很容易想到有奇偶两种情况,当为奇数(‘aba’)时l=r=i,然后分别向两边移动,当为偶数(‘aabb’)时l=i,r=i+1
def helper(s,l,r):
while l >= 0 and r < len(s) and s[l] == s[r]:
l -= 1
r += 1
return s[l+1:r]
def longs(s):
res = ''
for i in range(len(s)):
tmp = helper(s,i,i) # 奇数
if len(tmp) > len(res):res = tmp
tmp = helper(s,i,i+1) # 偶数
if len(tmp) > len(res):res = tmp
print(len(res))
s = input()
n = len(s)
longs(s)
1.2 动态规划
动态规划的想法也是非常简单的,假如i+1~j-1之间的字符串时回文字符串,那么如果s[i]==s[j]则i~j之间的字符串也是回文子串,如果不相等,那么则不是回文子串,由此可以列出状态转移方程dp[i][j]=dp[i+1][j-1] and s[i]==s[j]。然后我们考虑初始条件,如果i==j则dp[i][i]=True,一个字符肯定时回文串,两个字符和三个字符时则为dp[i][j] = (s[i] == s[j]),只需要考虑两边的字符即可。
可以看到,计算dp[i][j]用到了未来的状态dp[i+1][j],因此i需要反向迭代,即大到小。
| 原始字符串 | a | b | c | a | c | b | a |
|---|---|---|---|---|---|---|---|
| 子序列1 | a | b | b | a |
class Solution:
def longestPalindrome(self, s: str) -> str:
n = len(s)
dp = [[False for j in range(n)] for i in range(n)]
max_len = 0
max_str = ''
for i in range(n-1,-1,-1):
for j in range(i,n):
if s[i] == s[j]:
if j-i<=2:
dp[i][j] = True
else:
dp[i][j] = dp[i+1][j-1]
if dp[i][j] and j - i + 1 > max_len:
max_len = j - i + 1
max_str = s[i:j+1]
return max_str
最长回文子序列
子序列跟子串的一个最主要的区别在于是否连需,字符时不需要连需的,举个例子
| 原始字符串 | a | b | c | a | b | c | a |
|---|---|---|---|---|---|---|---|
| 子序列1 | a | b | b | a | |||
| 子序列2 | a | c | c | a | |||
| 子序列3 | a | a | a | ||||
| 子序列4 | a | c | a | c | a | ||
| 子序列5 | a | b | a | b | a | ||
| 子序列n | … |
可以看到回文子序列时完全不需要连续的,那么现在的问题就是如何求解最长子序列呢?假如我们求出了i+1~j-1之间的最长子序列,那么如何求解i~j之间的最长子序列呢?
| i | i+1 | j-1 | j | |||||
|---|---|---|---|---|---|---|---|---|
| s[i] | a | b | c | a | b | c | a | s[j] |
我们假设dp[i+1][j-1]是字符串i+1~j-1的最长回文子序列的长度,
- 当
s[i]==s[j]时,有dp[i][j] = dp[i+1][j-1]+2
| i | i+1 | j-1 | j | |||||
|---|---|---|---|---|---|---|---|---|
| s[i] | a | b | c | a | b | c | a | s[j] |
- 当
s[i]!=s[j]时,这个时候就有意思了,也会分成两种情况,第一种时求i+1~j之间的最长回文序列,第二种就是求i~j-1之间的最长回文子序列
| i | i+1 | j-1 | j | ||||||
|---|---|---|---|---|---|---|---|---|---|
| 原始 | s[i] | a | b | c | a | b | c | a | s[j] |
i+1~j | a | b | c | a | b | c | a | s[j] | |
i~j-1 | s[i] | a | b | c | a | b | c | a |
此时有dp[i][j]=max(dp[i][j-1],dp[i+1][j])
状态转移方程我们已经得到了,下一步就是看看base,可以知道dp[i][i]=1,因为我们时从i~j,所以有j>i,如果j<i,那么就不可能得到回文序列,因此有dp[i][j]=0 if j < i
现在就剩一个边界问题了,求dp[i][j]需要用到dp[i+1][j],即求解i位置的时候用到了未来的i+1位置,为了保证可以正常计算,我们需要将i按照递减的方式来更新,j则用到了j和j-1,所以使用递增计算即可
def longestPalindromeSubseq(self, s: str) -> int:
n = len(s)
dp = [[1 if i==j else 0 for i in range(n)] for j in range(n)]
for i in range(n-1,-1,-1):
for j in range(i+1,n):
if s[i] == s[j]:
dp[i][j] = dp[i+1][j-1] + 2
else:
dp[i][j] = max(dp[i+1][j],dp[i][j-1])
return dp[0][-1]
边栏推荐
- About HTTP cache control
- [combinatorics] Application of exponential generating function (multiple set arrangement problem | different balls in different boxes | derivation of exponential generating function of odd / even sequ
- node 开启服务器
- MySQL practice 45 lecture [transaction isolation]
- BigVision代码
- ffmpeg下载安装教程及介绍
- [mathematical logic] predicate logic (individual word | individual domain | predicate | full name quantifier | existence quantifier | predicate formula | exercise)
- Gavin teacher's perception of transformer live class - rasa project's actual banking financial BOT Intelligent Business Dialogue robot architecture, process and phenomenon decryption through rasa inte
- umi 路由拦截(简单粗暴)
- Vs 2019 configuration du moteur de génération de tensorrt
猜你喜欢

FileZilla client download and installation
![[MySQL] the difference between left join, right join and join](/img/d4/8684cd59cd1bd77e70bd4d7c7074c3.jpg)
[MySQL] the difference between left join, right join and join

Pytoch lightweight visualization tool wandb (local)

VS 2019 配置tensorRT生成engine

docker安装及启动mysql服务

The idea cannot be loaded, and the market solution can be applied (pro test)

Gavin teacher's perception of transformer live class - rasa project's actual banking financial BOT Intelligent Business Dialogue robot architecture, process and phenomenon decryption through rasa inte

Docker install and start MySQL service
![Mongodb replication set [master-slave replication]](/img/2c/8030548455f45fa252062dd90e7b8b.png)
Mongodb replication set [master-slave replication]

Lvgl usage experience
随机推荐
MongoDB主配置文件
PAT乙级常用函数用法总结
程序员新人上午使用 isXxx 形式定义布尔类型,下午就被劝退?
C programming learning notes [edited by Mr. Tan Haoqiang] (Chapter III sequence programming) 03 operators and expressions
Limit of one question per day
Agile certification (professional scrum Master) simulation exercise-2
文件重命名
Using jasmine to monitor constructors - spying on a constructor using Jasmine
C programming learning notes [edited by Mr. Tan Haoqiang] (Chapter III sequence programming) 05 data input and output
el-tree搜索方法使用
[combinatorics] brief introduction to generating function (definition of generating function | Newton binomial coefficient | commonly used generating function | correlation with constant | correlation
Limit of one question per day
Spark on yarn resource optimization ideas notes
Vs 2019 installation and configuration opencv
Idea format code idea set shortcut key format code
MySQL MAC download and installation tutorial
Gavin teacher's perception of transformer live class - rasa project's actual banking financial BOT Intelligent Business Dialogue robot architecture, process and phenomenon decryption through rasa inte
VS克隆时显示403错误
用Three.js做一个简单的3D场景
File rename