1. La subcadena palíndromo más larga
Esta pregunta debe ser explicada con cuidado. La he hecho varias veces y luego la olvidé después de un período de tiempo. Entonces, en resumen, sáquela cuando la olvide y use dos métodos más comprensibles para hacerlo.
Primero ve al código de programación dinámica
class Solution:
def longestPalindrome(self, s: str) -> str:
if not s:
return ''
n = len(s)
maxlen = 0
res = 0
dp = [[False for _ in range(n)]for _ in range(n)]
for j in range(n):
for i in range(j+1):
dp[i][j] = s[i]==s[j] and (j-i<=2 or dp[i+1][j-1])
if dp[i][j]:
if j-i+1>maxlen:
maxlen = j-i+1
res = s[i:j+1]
return res
Tome s = 'babad' como ejemplo, j sigue yendo hacia atrás, i es de 0 a j, y juzga constantemente, por lo que el bucle for de dos capas se escribe como en el código, cuando j = 4, i va de 0 a 4. Luego ve a buscar el palíndromo más largo
Por supuesto, hay otras formas de escribir el bucle for de dos capas, la imagen proviene de la fuente
dp [i] [j] indica si s [i] ys [j] son iguales. Si son iguales, y dp [i + 1] [j-1] también es igual, significa que el anterior es un palíndromo subcadena y luego agregue Ir a estos dos ahora. Entonces dp [i] [j] = s [j] == s [j] && dp [i + 1] [j-1], pero mirando el código, también hay una opción ji <= 2 para lo siguiente razones:
s = 'babad', cuando i = 0, j = 2, ji = 2 y s [j] == s [j], solo un elemento a en el medio es definitivamente un palíndromo, por lo que no hay necesidad de juzgar dp [i + 1] [j-1], está directamente a la derecha.
Y j-i <= 2 debe escribirse antes de dp [i + 1] [j-1], de lo contrario se informará un error, porque cuando i = 1, j = 2, si escribe dp [i + 1] [j- 1], entonces i se convierte en 2 y j se convierte en 1, lo cual es incorrecto según el análisis de este momento, porque j está retrocediendo constantemente, e i es de 0 a j, i está más allá de j, así que de ninguna manera. Las otras partes se entienden mejor, así que no las explicaré
El segundo método:
class Solution:
def __init__(self):
self.res = ''
def longestPalindrome(self, s: str) -> str:
if not s:
return ''
for i in range(len(s)):
self.helper(s,i,i)
self.helper(s,i,i+1)
return self.res
def helper(self,s,left,right):
while left>=0 and right<len(s) and s[left]==s[right]:
left-=1
right+=1
cur = s[left+1:right]
if len(cur)>len(self.res):
self.res = cur
Este método adopta el método de difusión central.
Extienda desde el medio hacia ambos lados, pero la longitud de la cuerda puede ser par o impar, así que escríbala dos veces directamente, el resultado es el mismo
2. La subsecuencia palíndromo más larga
Codificar primero
class Solution:
def longestPalindromeSubseq(self, s: str) -> int:
if not s:
return 0
n = len(s)
dp = [[0 for _ in range(n)]for _ in range(n)]
for i in range(n):
dp[i][i] = 1
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][j-1],dp[i+1][j])
return dp[0][n-1]
El código central es el siguiente, de hecho, es más fácil de entender. Si las letras en ambos extremos son iguales, agregue 2 a la longitud, de lo contrario, depende de la longitud de las subcadenas en ambos lados y tome la más larga.
if s[i]==s[j]:
dp[i][j] = dp[i+1][j-1]+2
else:
dp[i][j] = max(dp[i][j-1],dp[i+1][j])
Para dos bucles for, el primer bucle for establece la posición de i desde la parte posterior. Si la cadena es "bbbab", cuando i apunta a la segunda posición, j comienza desde la tercera y va hacia atrás y compara secuencialmente la letra en la i -th posición