Langste palindromische subsequence en substring
Pas interval-DP toe om de langste palindromische subsequence te vinden en gebruik de techniek waarbij u vanuit het midden naar buiten uitbreidt voor de langste palindromische substring.
Langste palindromische subsequence en substring is een gratis Voorbereiding op programmeerinterviews-les op CoddyKit. Dit is les 2 van 4. Je kunt de volledige les hieronder gratis lezen en daarna in de browser praktisch oefenen met een ingebouwde code-editor en een AI-begeleider die 24/7 beschikbaar is. Deze les maakt deel uit van het leertraject Voorbereiding op programmeerinterviews. Je voortgang wordt gesynchroniseerd op het web en in de CoddyKit-app. De cursus Voorbereiding op programmeerinterviews bevat in totaal 4 lessen.
Palindroomdefinities opnieuw bekeken
Een palindromische deelrij is een deelrij (waarvan de elementen niet per se aaneengesloten zijn) die van voren naar achteren en omgekeerd hetzelfde leest. Een palindromische deelstring vereist aaneengesloten tekens. Voor 'bbbab' is de langste palindromische deelrij 'bbbb' (lengte 4), terwijl de langste palindromische deelstring 'bbb' is (lengte 3). Deze twee problemen vereisen verschillende technieken, ondanks hun vergelijkbare namen.
Toestand van de langste palindromische deelrij: LPS
Definieer dp[i][j] als de lengte van de langste palindromische deelrij in s[i..j]. De recursieformule is: als s[i] == s[j], dan is dp[i][j] = dp[i+1][j-1] + 2 (de twee gelijke tekens breiden het binnenste palindroom uit). Anders is dp[i][j] = max(dp[i+1][j], dp[i][j-1]) (sla het teken links of rechts over). Basisgeval: dp[i][i] = 1 voor elk afzonderlijk teken.
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')LPS-vulvolgorde en implementatie
We vullen de LPS-tabel in volgorde van oplopende intervallengte in, volgens hetzelfde patroon als algemene interval-DP. Voor elk interval [i, j] met lengte 2 of meer controleren we of de twee grenswaarden gelijk zijn en passen we de recursieformule toe. Het uiteindelijke antwoord is dp[0][n-1], de LPS van de volledige tekenreeks.
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 via LCS-equivalentie
Een elegant alternatief: de LPS van tekenreeks s is gelijk aan de LCS van s en de omgekeerde tekenreeks s[::-1]. Dat komt doordat elke palindromische deelrij van s een gemeenschappelijke deelrij is van s en de omgekeerde tekenreeks. Dankzij deze omzetting kun je je LCS-code rechtstreeks hergebruiken. De omgekeerde versie van 'bbbab' is 'babbb' en hun LCS heeft lengte 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')) # 4Langste palindromische deelstring: uitputtend zoeken
De langste palindromische deelstring vereist aaneengesloten tekens. Een uitputtende aanpak controleert alle O(n²) deelstrings en verifieert elke deelstring in O(n) tijd — in totaal O(n³). Er bestaan twee snellere aanpakken: interval-DP in O(n²) tijd en ruimte en uitbreiden rond het midden in O(n²) tijd maar O(1) ruimte. Voor sollicitatiegesprekken heeft uitbreiden rond het midden de voorkeur, omdat de constante factor kleiner is en de code overzichtelijker.
Interval-DP voor palindromische deelstrings
Definieer dp[i][j] = True als s[i..j] een palindroom is. Recursieformule: dp[i][j] = (s[i] == s[j]) and dp[i+1][j-1]. Basisgevallen: dp[i][i] = True en dp[i][i+1] = (s[i] == s[i+1]). Houd de langste gevonden palindroom bij. Vul de tabel in volgorde van oplopende lengte in. Dit werkt in O(n²) tijd en O(n²) ruimte.
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'Techniek voor uitbreiden rond het midden
De aanpak uitbreiden rond het midden probeert elk teken en elk paar aangrenzende tekens als mogelijk palindroommidden en breidt naar buiten uit zolang beide zijden overeenkomen. Er zijn 2n-1 mogelijke middelpunten (n voor palindromen met oneven lengte en n-1 voor palindromen met even lengte). Elke uitbreiding kost hoogstens O(n) tijd, wat in totaal O(n²) oplevert met O(1) ruimte — optimaal voor de meeste sollicitatiegesprekken.
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'LPS-ruimteoptimalisatie
De interval-DP voor LPS gebruikt O(n²) ruimte. Wanneer je alleen de lengte nodig hebt en niet de daadwerkelijke deelrij, kun je de ruimte beperken door te zien dat dp[i][j] alleen afhankelijk is van dp[i+1][j-1], dp[i+1][j] en dp[i][j-1]. Door rijen opnieuw te gebruiken en één diagonaalwaarde te bewaren, kun je O(n) ruimte bereiken — hoewel de implementatie complexer is en zelden nodig is tijdens sollicitatiegesprekken.
De LPS reconstrueren
Om de daadwerkelijke palindromische deelrij te reconstrueren, loop je terug door de DP-tabel. Begin bij (0, n-1). Als s[i] == s[j], voeg je dat teken aan beide uiteinden van je resultaat toe en ga je naar (i+1, j-1). Ga anders naar (i+1, j) of (i, j-1), afhankelijk van welke de grotere waarde heeft. Met deze hebzuchtige terugloop reconstrueer je op unieke wijze één optimale palindromische deelrij.
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')Tijdscomplexiteit van LPS en LCS vergelijken
Zowel LPS via interval-DP als LCS werken in O(n²) tijd en O(n²) ruimte. Uitbreiden rond het midden voor de langste palindromische deelstring kost O(n²) tijd maar slechts O(1) ruimte. Het algoritme van Manacher lost het deelstringprobleem op in O(n) tijd en ruimte, maar is zo complex dat interviewers het zelden verwachten. In de meeste contexten van sollicitatiegesprekken is uitbreiden rond het midden de verwachte optimale oplossing voor de variant met deelstrings.
Veelvoorkomende valkuilen en randgevallen
Let op deze valkuilen: (1) een niet-aaneengesloten deelreeks verwarren met een aaneengesloten deelreeks — het zijn verschillende problemen met verschillende oplossingen; (2) voor het basisgeval van interval-dp met intervallen van lengte 2 is speciale afhandeling nodig, omdat dp[i+1][j-1] gelijk zou zijn aan dp[i+1][i] (leeg interval); (3) initialiseer bij uitbreiden rond het midden max_len = 1 (elk afzonderlijk teken is een palindroom); en (4) bereken bij het ophalen van het resultaat start = i - (best-1)//2 om de startindex correct vanuit het midden te bepalen.
Korte toets
Toets je begrip van de concepten uit Data Structures & Algorithms — Coding Interview Prep van deze les.
Samenvatting van de les
In deze les heb je geleerd: LPS gebruikt interval-dp met de recurrentie dp[i][j] = dp[i+1][j-1]+2 wanneer de tekens overeenkomen, de langste palindromische deeltekenreeks los je het best op met uitbreiden rond het midden in O(n²) tijd en O(1) ruimte, en LPS is gelijk aan LCS van de tekenreeks en het omgekeerde daarvan. Hierna behandelen we palindroompartitionering II, waarin een palindroomtabel wordt gecombineerd met 1D-dp voor het minimale aantal knippen.
Leer Voorbereiding op programmeerinterviews met een AI-tutor — gratis
Schrijf echte code en voer die uit in je browser, krijg direct hulp van een AI-tutor die 24/7 beschikbaar is en ga verder waar je gebleven bent op het web of in de app.
- Cursussen
- 90
- Lessen
- 360
Veelgestelde vragen
Is de les “Langste palindromische subsequence en substring” gratis?
Ja — de volledige tekst van “Langste palindromische subsequence en substring” kun je hier gratis op het web lezen. Als je interactief wilt oefenen met een ingebouwde code-editor en een AI-begeleider die 24/7 beschikbaar is, en de rest van de cursus Voorbereiding op programmeerinterviews wilt ontgrendelen, kun je upgraden naar CoddyKit PRO. De cursus Voorbereiding op programmeerinterviews bevat in totaal 4 lessen.
Wat leer ik in “Langste palindromische subsequence en substring”?
Pas interval-DP toe om de langste palindromische subsequence te vinden en gebruik de techniek waarbij u vanuit het midden naar buiten uitbreidt voor de langste palindromische substring. Je oefent met Voorbereiding op programmeerinterviews door code rechtstreeks in de browser uit te voeren. Een AI-begeleider die 24/7 beschikbaar is beantwoordt je vragen terwijl je de les doorwerkt.
Heb ik ervaring nodig om met Voorbereiding op programmeerinterviews te beginnen?
Ervaring vooraf is niet nodig. Voorbereiding op programmeerinterviews op CoddyKit is opgebouwd voor beginners tot gevorderden, zodat je hier of bij het begin kunt starten en in je eigen tempo kunt leren. Dit is les 2 van 4.
Hoe lang duurt de les “Langste palindromische subsequence en substring”?
De meeste lessen van CoddyKit duren ongeveer 5–10 minuten. Elke les is kort en interactief, zodat je gestaag vooruitgaat en op het web en in de app precies verdergaat waar je was gebleven.
Kan ik code schrijven en uitvoeren in deze les over Voorbereiding op programmeerinterviews?
Ja. Elke les over Voorbereiding op programmeerinterviews bevat een ingebouwde code-editor, zodat je rechtstreeks in je browser echte code kunt schrijven en uitvoeren en direct feedback van AI krijgt — lokale installatie is niet nodig.
Alle lessen in deze cursus
- Interval-DP-patroon en vulvolgorde
- Langste palindromische subsequence en substring
- Palindrome Partitioning II
- Burst Balloons: interval-DP in omgekeerde richting