PrepStack · Markdown HTML

Subsequence dynamic programming

Dynamic programming · HTML

Formal shape

One sequence: dp[i] is the best subsequence ending at i, considering compatible j<i. Two sequences: dp[i][j] describes prefixes A[:i],B[:j]; matching ends pair, while mismatch skips a side or applies an edit.

Recognition signals

False friends

SignalWhy it is different
A contiguous subarray or substringContiguity favors a window, prefix aggregate, or local DP and does not permit arbitrary skips.
One subsequence-containment checkA single query is handled by two pointers in linear time.
Unordered set matchingIf relative order is irrelevant, hashing, frequency counts, or graph matching may fit better.

Core invariant

Every computed state exactly matches its endpoint/prefix definition and includes all legal final match, skip, or edit actions.

State, transition, and processing order

ItemDefinition
StateOne ending index i or two prefix lengths (i,j), optionally with parent/action data for reconstruction.
TransitionReason from the final action: pair equal ends, skip A's end, skip B's end, or perform replacement/insertion/deletion and aggregate.
Frontier / orderIncrease i and j in dependency-DAG order. Two-dimensional rows can roll, though witness reconstruction usually needs more information.

Python skeleton

def lcs_length(a, b):
    prev = [0] * (len(b) + 1)
    for x in a:
        cur = [0]
        for j, y in enumerate(b, 1):
            if x == y:
                cur.append(prev[j - 1] + 1)
            else:
                cur.append(max(prev[j], cur[-1]))
        prev = cur
    return prev[-1]

Correctness sketch

  1. The common subsequence length with an empty prefix is zero.
  2. If final symbols match, an optimum may pair them and extend the shorter prefixes; if they differ, every optimum skips at least one final symbol.
  3. The recurrence covers these final actions, and induction on prefix lengths proves the answer.

Complexity

TimeSpaceParameters
Typically O(mn) for two sequences and O(n²) for a naive one-sequence formO(min(m,n)) for length with rolling rows; often O(mn) for reconstructionm and n are sequence lengths.

Edge cases

Error patterns

PatternWhy it fails / fix
Confusing subsequence with substringA subsequence permits gaps; the state and recurrence must reflect skips.
Assuming a match always removes all alternativesThat safety depends on the objective; generalized costs may still require comparing other actions.
Aliasing rolling rowsprev and cur must be distinct layers, or current-row updates contaminate prior-prefix states.
Storing only length when a witness is requiredKeep parents/full table or use a separate divide-and-conquer reconstruction.

Selection and exclusion rules

RelationTemplateBoundary
specializationLinear dynamic programmingA state ends at one position or relates two prefixes.

Original micro-example

PartDetail
ResultThe length is 2; either 'cb' or 'ab' is a witness.
SetupA='cab' and B='acb'; find their common-subsequence length.
TraceBoth end in b, so extend the length 1 answer for prefixes 'ca' and 'ac'.

Recall prompts

My notes