Plus longue sous-séquence et sous-chaîne palindromiques
Appliquez la DP sur intervalles pour trouver la plus longue sous-séquence palindromique et l’astuce d’expansion autour du centre pour la plus longue sous-chaîne palindromique.
Plus longue sous-séquence et sous-chaîne palindromiques est une leçon DSA Interview Prep gratuite sur CoddyKit. Ceci est la leçon 2 sur 4. Tu peux lire la leçon complète ci-dessous gratuitement — puis la pratiquer en direct dans le navigateur avec un éditeur de code intégré et un tuteur IA 24/7. Elle fait partie du parcours d'apprentissage DSA Interview Prep, et ta progression se synchronise sur le web et l'application CoddyKit. Le cours DSA Interview Prep comprend 4 leçons au total.
Définitions des palindromes revisitées
Une sous-séquence palindromique est une sous-séquence (dont les éléments ne sont pas nécessairement contigus) qui se lit de la même façon dans les deux sens. Une sous-chaîne palindromique doit être composée de caractères contigus. Pour 'bbbab', la plus longue sous-séquence palindromique est 'bbbb' (de longueur 4), tandis que la plus longue sous-chaîne palindromique est 'bbb' (de longueur 3). Ces deux problèmes nécessitent des techniques différentes malgré leurs noms similaires.
Plus longue sous-séquence palindromique : état LPS
Définissez dp[i][j] comme la longueur de la plus longue sous-séquence palindromique dans s[i..j]. La récurrence est la suivante : si s[i] == s[j], alors dp[i][j] = dp[i+1][j-1] + 2 (les deux caractères identiques prolongent le palindrome intérieur). Sinon, dp[i][j] = max(dp[i+1][j], dp[i][j-1]) (ignorez le caractère gauche ou droit). Cas de base : dp[i][i] = 1 pour chaque caractère seul.
s = 'bbbab'
n = len(s)
dp = [[0]*n for _ in range(n)]
for i in range(n):
dp[i][i] = 1
print('Base cases set, dp[i][i] = 1 for all i')Ordre de remplissage et mise en œuvre de LPS
Nous remplissons le tableau LPS selon une longueur d'intervalle croissante, comme pour la DP sur intervalles générale. Pour chaque intervalle [i, j] de longueur 2 ou plus, nous vérifions si les deux caractères aux limites sont identiques et appliquons la récurrence. Le résultat final est dp[0][n-1], c'est-à-dire la LPS de la chaîne entière.
def longest_palindromic_subsequence(s):
n = len(s)
dp = [[0]*n for _ in range(n)]
for i in range(n):
dp[i][i] = 1
for length in range(2, n+1):
for i in range(n - length + 1):
j = i + length - 1
if s[i] == s[j]:
inner = dp[i+1][j-1] if length > 2 else 0
dp[i][j] = inner + 2
else:
dp[i][j] = max(dp[i+1][j], dp[i][j-1])
return dp[0][n-1]
print(longest_palindromic_subsequence('bbbab')) # 4LPS par équivalence avec LCS
Voici une alternative élégante : la LPS de la chaîne s est égale à la LCS de s et de son inverse s[::-1]. Cela s'explique par le fait que toute sous-séquence palindromique de s est une sous-séquence commune de s et de son inverse. Cette réduction vous permet de réutiliser directement votre code de LCS. Pour 'bbbab', l'inverse est 'babbb', et leur LCS vaut 4.
def lps_via_lcs(s):
t = s[::-1]
m, n = len(s), len(t)
dp = [[0]*(n+1) for _ in range(m+1)]
for i in range(1, m+1):
for j in range(1, n+1):
if s[i-1] == t[j-1]:
dp[i][j] = dp[i-1][j-1] + 1
else:
dp[i][j] = max(dp[i-1][j], dp[i][j-1])
return dp[m][n]
print(lps_via_lcs('bbbab')) # 4Plus longue sous-chaîne palindromique : force brute
La plus longue sous-chaîne palindromique doit être composée de caractères contigus. Une approche par force brute examine toutes les sous-chaînes O(n²) et vérifie chacune en O(n) time — soit O(n³) au total. Deux approches plus rapides existent : la DP sur intervalles en O(n²) time et espace, et l'expansion autour du centre en O(n²) time mais O(1) espace. En entretien, l'expansion autour du centre est préférable, car elle possède une constante plus faible et un code plus clair.
DP sur intervalles pour les sous-chaînes palindromiques
Définissez dp[i][j] = True si s[i..j] est un palindrome. Récurrence : dp[i][j] = (s[i] == s[j]) and dp[i+1][j-1]. Cas de base : dp[i][i] = True et dp[i][i+1] = (s[i] == s[i+1]). Conservez le palindrome de longueur maximale trouvé. Remplissez le tableau selon un ordre de longueur croissante. Cette méthode s'exécute en O(n²) time et utilise O(n²) espace.
def longest_palindrome_dp(s):
n = len(s)
dp = [[False]*n for _ in range(n)]
start, max_len = 0, 1
for i in range(n):
dp[i][i] = True
for i in range(n-1):
if s[i] == s[i+1]:
dp[i][i+1] = True
start, max_len = i, 2
for length in range(3, n+1):
for i in range(n - length + 1):
j = i + length - 1
if s[i] == s[j] and dp[i+1][j-1]:
dp[i][j] = True
if length > max_len:
start, max_len = i, length
return s[start:start+max_len]
print(longest_palindrome_dp('babad')) # 'bab' or 'aba'Technique d'expansion autour du centre
L'approche d'expansion autour du centre considère chaque caractère (ainsi que chaque paire de caractères adjacents) comme un centre potentiel de palindrome et s'étend vers l'extérieur tant que les deux côtés correspondent. Il existe 2n-1 centres possibles (n pour les palindromes de longueur impaire et n-1 pour ceux de longueur paire). Chaque expansion prend au plus O(n) time, ce qui donne O(n²) au total avec O(1) espace — une solution optimale dans la plupart des contextes d'entretien.
def longest_palindrome_expand(s):
def expand(l, r):
while l >= 0 and r < len(s) and s[l] == s[r]:
l -= 1
r += 1
return r - l - 1 # length of palindrome
start, max_len = 0, 1
for i in range(len(s)):
odd = expand(i, i) # odd-length
even = expand(i, i+1) # even-length
best = max(odd, even)
if best > max_len:
max_len = best
start = i - (best - 1) // 2
return s[start:start+max_len]
print(longest_palindrome_expand('cbbd')) # 'bb'Optimisation de l'espace pour LPS
La DP sur intervalles pour LPS utilise O(n²) espace. Lorsque vous n'avez besoin que de la longueur (et non de la sous-séquence elle-même), vous pouvez réduire l'espace en observant que dp[i][j] dépend uniquement de dp[i+1][j-1], dp[i+1][j] et dp[i][j-1]. En réutilisant les lignes et en conservant une valeur diagonale, vous pouvez atteindre O(n) espace — même si la mise en œuvre est plus complexe et rarement nécessaire en entretien.
Reconstruction de LPS
Pour reconstruire la sous-séquence palindromique réelle, remontez dans le tableau de DP. Commencez à (0, n-1). Si s[i] == s[j], ajoutez ce caractère aux deux extrémités de votre résultat et passez à (i+1, j-1). Sinon, avancez vers celui de (i+1, j) ou (i, j-1) qui possède la plus grande valeur. Cette remontée gloutonne permet de retrouver de manière unique une sous-séquence palindromique optimale.
def reconstruct_lps(s, dp):
result = []
i, j = 0, len(s) - 1
while i < j:
if s[i] == s[j]:
result.append(s[i])
i += 1; j -= 1
elif dp[i+1][j] > dp[i][j-1]:
i += 1
else:
j -= 1
# middle character for odd-length
mid = [s[i]] if i == j else []
return ''.join(result + mid + result[::-1])
print('Traceback recovers one optimal LPS')Comparaison de la complexité en temps de LPS et LCS
La LPS par DP sur intervalles et la LCS s'exécutent toutes deux en O(n²) time et O(n²) espace. L'expansion autour du centre pour la plus longue sous-chaîne palindromique utilise O(n²) time, mais seulement O(1) espace. L'algorithme de Manacher résout le problème des sous-chaînes en O(n) time et espace, mais il est suffisamment complexe pour que les recruteurs l'attendent rarement. Dans la plupart des contextes d'entretien, l'expansion autour du centre est la solution optimale attendue pour la variante des sous-chaînes.
Pièges courants et cas limites
Attention aux pièges suivants : (1) confondre une sous-séquence avec une sous-chaîne — ce sont des problèmes différents, qui ont des solutions différentes ; (2) le cas de base de la DP par intervalles pour les intervalles de longueur 2 nécessite un traitement particulier, car dp[i+1][j-1] deviendrait dp[i+1][i] (intervalle vide) ; (3) pour l’expansion autour du centre, initialisez max_len = 1 (chaque caractère isolé est un palindrome) ; et (4) lors de l’extraction du résultat, calculez start = i - (best-1)//2 afin de trouver correctement l’indice de début à partir du centre.
Vérification rapide
Vérifiez votre compréhension des concepts de Structures de données et algorithmes — Préparation aux entretiens de programmation présentés dans cette leçon.
Récapitulatif de la leçon
Dans cette leçon, vous avez appris : LPS utilise une DP par intervalles avec la récurrence dp[i][j] = dp[i+1][j-1]+2 lorsque les caractères correspondent, la sous-chaîne palindromique la plus longue se résout au mieux par expansion autour du centre en O(n²) et avec un espace O(1), et LPS est égal au LCS de la chaîne et de son inverse. Nous allons ensuite aborder le partitionnement en palindromes II, qui combine une table des palindromes avec une DP 1D pour trouver le nombre minimal de coupes.
Questions Fréquemment Posées
La leçon « Plus longue sous-séquence et sous-chaîne palindromiques » est-elle gratuite ?
Oui — le texte complet de « Plus longue sous-séquence et sous-chaîne palindromiques » est gratuit à lire ici sur le web. Pour la pratiquer de manière interactive (un éditeur de code intégré et un tuteur IA 24/7) et déverrouiller le reste du cours DSA Interview Prep, passe à CoddyKit PRO. Le cours DSA Interview Prep comprend 4 leçons au total.
Qu'est-ce que j'apprendrai dans « Plus longue sous-séquence et sous-chaîne palindromiques » ?
Appliquez la DP sur intervalles pour trouver la plus longue sous-séquence palindromique et l’astuce d’expansion autour du centre pour la plus longue sous-chaîne palindromique. Tu pratiques DSA Interview Prep avec du code pratique que tu exécutes directement dans le navigateur, et un tuteur IA 24/7 répond à tes questions au fur et à mesure que tu avances dans la leçon.
Dois-je avoir de l'expérience pour commencer DSA Interview Prep ?
Aucune expérience préalable n'est requise. DSA Interview Prep sur CoddyKit est structuré pour les débutants jusqu'aux apprenants avancés, donc tu peux commencer ici ou depuis le début et avancer à ton rythme. Ceci est la leçon 2 sur 4.
Combien de temps prend la leçon « Plus longue sous-séquence et sous-chaîne palindromiques » ?
La plupart des leçons CoddyKit prennent environ 5–10 minutes. Chacune est courte et interactive, tu progresses régulièrement et tu repiques exactement où tu t'es arrêté sur le web et l'app.
Peux-tu écrire et exécuter du code dans cette leçon DSA Interview Prep ?
Oui. Chaque leçon DSA Interview Prep inclut un éditeur de code intégré, tu écris et exécutes du vrai code directement dans ton navigateur et tu reçois des retours IA instantanés — aucune configuration locale requise.
Toutes les leçons de ce cours
- Schéma de DP sur les intervalles et ordre de remplissage
- Plus longue sous-séquence et sous-chaîne palindromiques
- Partitionnement palindromique II
- Ballons à éclater : DP sur intervalles inversée