What if two long sequences share one important region, but the rest is unrelated? A global alignment can be forced to explain too much. Smith–Waterman solves a different problem: find the best-scoring local alignment between two sequences. That makes it a powerful case study in dynamic programming, because one small change to the recurrence — resetting negative scores to zero — changes the meaning of the entire computation.
This article teaches Smith–Waterman from a small character example to professional bioinformatics implementation concerns. It complements the broader Edit-Distance Algorithms article, whose job is the wider family of sequence-comparison methods.
Quick Read
- Smith–Waterman finds an optimal local alignment under the chosen scoring system.
- It fills a dynamic-programming matrix using match/mismatch and gap choices.
- The recurrence includes zero, which means a bad partial alignment may be abandoned and restarted.
- The highest-scoring cell is the end of the best local alignment; traceback stops when a zero is reached.
- Professional implementations care about substitution matrices, affine gap penalties, memory layout, vectorisation, database scale and the biological meaning of the score.
1. Beginner Level: Global Versus Local Questions
Suppose sequence A is TTACGTA and sequence B is GGACGTT. The middle parts look strongly related: ACGT. A global method tries to align the sequences from end to end. Smith–Waterman is allowed to ignore weak prefixes and suffixes and concentrate on the strongest region.
This distinction is not cosmetic. Before choosing an algorithm, decide what the question means. “How similar are these complete sequences?” and “Where is their strongest common region?” are different computational jobs.
2. The Dynamic-Programming State
Let H[i, j] be the best score of a local alignment that ends at positions i and j of the two sequences. The simplest teaching recurrence uses a match reward, mismatch penalty and linear gap penalty:
H[i,j] = max(0, H[i−1,j−1] + score(aᵢ,bⱼ), H[i−1,j] − gap, H[i,j−1] − gap).
- Diagonal: align the two current symbols.
- Up: align a symbol from the first sequence with a gap.
- Left: align a gap with a symbol from the second sequence.
- Zero: abandon the current partial alignment and start fresh later.
The zero is the conceptual heart of Smith–Waterman. If every way of extending the current local alignment would produce a negative score, carrying that history forward cannot help a future optimum. Resetting to zero removes harmful baggage.
3. A Tiny Worked Example
Use A = ACG, B = AG, match = +2, mismatch = −1, gap = −2. Initialise the first row and first column of H to zero.
At H[1,1], A matches A, so the diagonal gives 0 + 2 = 2. The gap alternatives are negative, so H[1,1] = 2. At H[2,2], C versus G mismatches; the diagonal gives 2 − 1 = 1, while gap alternatives are no better, so H[2,2] = 1. At H[3,2], G matches G, and the diagonal from H[2,1] can produce a positive score. The best cell across the matrix identifies the end of the strongest local alignment.
For a learner, the most useful activity is to fill the matrix by hand and write the winning predecessor beside every positive cell. That converts a recurrence from symbols into a sequence of decisions.
4. Why the Traceback Starts at the Maximum
Global alignment usually starts traceback from the bottom-right corner because the solution must reach both sequence ends. Smith–Waterman starts from the largest value anywhere in H. That cell says: “the best local alignment seen in the whole table ends here.”
Trace backward through the predecessor choices until a cell with score zero is reached. That zero marks the point before which extending the alignment was not worth keeping.
5. Pseudocode
create H with (m+1) rows and (n+1) columns, filled with zero
best_score = 0
best_cell = (0, 0)
for i = 1..m:
for j = 1..n:
diagonal = H[i-1][j-1] + substitution_score(A[i-1], B[j-1])
delete = H[i-1][j] - gap_penalty
insert = H[i][j-1] - gap_penalty
H[i][j] = max(0, diagonal, delete, insert)
if H[i][j] > best_score:
best_score = H[i][j]
best_cell = (i, j)
trace back from best_cell until a zero is reached
6. A Readable Python Version
def smith_waterman(a, b, match=2, mismatch=-1, gap=-2):
m, n = len(a), len(b)
H = [[0] * (n + 1) for _ in range(m + 1)]
parent = [[None] * (n + 1) for _ in range(m + 1)]
best_score = 0
best = (0, 0)
for i in range(1, m + 1):
for j in range(1, n + 1):
s = match if a[i - 1] == b[j - 1] else mismatch
candidates = [
(0, None),
(H[i - 1][j - 1] + s, "diag"),
(H[i - 1][j] + gap, "up"),
(H[i][j - 1] + gap, "left"),
]
score, move = max(candidates, key=lambda x: x[0])
H[i][j] = score
parent[i][j] = move
if score > best_score:
best_score = score
best = (i, j)
i, j = best
aa, bb = [], []
while i > 0 and j > 0 and H[i][j] > 0:
move = parent[i][j]
if move == "diag":
aa.append(a[i - 1]); bb.append(b[j - 1])
i -= 1; j -= 1
elif move == "up":
aa.append(a[i - 1]); bb.append("-")
i -= 1
elif move == "left":
aa.append("-"); bb.append(b[j - 1])
j -= 1
else:
break
return best_score, "".join(reversed(aa)), "".join(reversed(bb))
This version is intentionally transparent. Professional biological alignment normally uses richer scoring and more memory-efficient data structures.
7. From Linear Gaps to Affine Gap Penalties
A single gap of length five is usually not biologically equivalent to five unrelated one-symbol gaps. A common model therefore charges a larger gap-open penalty and a smaller gap-extension penalty. Gotoh’s improvement represents this with multiple dynamic-programming states so that extending an existing gap has a different cost from opening a new one.
This is an excellent advanced lesson in state design. The recurrence becomes more complicated because the algorithm must remember not only the best score at a coordinate, but also whether the alignment currently ends in a match/mismatch, a gap in one sequence, or a gap in the other.
8. Substitution Matrices Change the Meaning of “Match”
For toy strings, +2 for an equal symbol and −1 for an unequal symbol is enough. Protein alignment is different. Replacing one amino acid with another may be relatively conservative or biologically unlikely. Practical systems therefore use substitution matrices such as BLOSUM families rather than a single mismatch penalty.
The algorithm optimises whatever scoring model you provide. It cannot tell you whether the scoring model is scientifically appropriate. This is a recurring professional principle: algorithmic optimality is conditional on the objective being the right objective.
9. Complexity and Memory
For sequence lengths m and n, the standard dynamic program evaluates O(mn) cells. If the full table and traceback information are stored, memory is also O(mn). If only the best score is required, two rows can be enough, reducing working memory to O(n) for the shorter dimension.
Exact local alignment therefore becomes expensive for long database searches. That explains why production bioinformatics often combines exact algorithms, heuristics, vectorisation, indexing and specialised hardware according to the receiver’s speed and accuracy requirements.
10. SIMD and the Professional Performance Layer
The recurrence has regular arithmetic but also dependencies between cells. High-performance implementations reorganise the calculation to exploit vector instructions. Michael Farrar’s striped Smith–Waterman formulation is a classic example: it lays out data so that SIMD lanes can update multiple cells efficiently while respecting dependencies. Modern implementations may also use wider vector instructions, GPUs or accelerator-specific kernels.
The important educational bridge is that asymptotic complexity is only one layer of performance. Two O(mn) implementations can differ dramatically because of memory layout, instruction-level parallelism, cache behaviour and data representation.
11. Failure Modes and Misconceptions
- Local is not global: Smith–Waterman may ignore most of both sequences.
- Score is not probability: a high alignment score needs an appropriate statistical or biological interpretation.
- Scoring matters: changing substitution or gap penalties can change the optimal alignment.
- Ties matter: multiple alignments may share the same optimal score.
- Full matrix costs memory: a naive implementation can become impractical on very long sequences.
- Exact does not mean universally best: exact local alignment may be too expensive for a huge search workload.
- Similarity is not automatically homology: biological conclusions require domain knowledge and evidence beyond an algorithmic score.
12. Learning Progression: Beginner to Professional
- Beginner: fill a 4×4 score matrix with simple match/mismatch/gap values.
- Intermediate: implement traceback and explain why it starts at the maximum and stops at zero.
- Advanced: add affine gap penalties and substitution matrices.
- Professional: benchmark memory layout, vectorisation, exact-versus-heuristic trade-offs and biological scoring assumptions.
13. Practice Problems
- Compute a Smith–Waterman matrix for
GATTandGCAT. - Change the mismatch penalty from −1 to −4 and explain how the optimum changes.
- Compare linear and affine gap penalties on sequences containing one long insertion.
- Modify the implementation to return all tied highest-scoring endpoints.
- Reduce score-only memory from O(mn) to O(n).
- Profile a scalar implementation against a library implementation and identify where the speed difference comes from.
14. Sources and Further Reading
- Smith & Waterman (1981), Identification of common molecular subsequences.
- EMBOSS water documentation for Smith–Waterman local alignment.
- Farrar (2007), striped SIMD Smith–Waterman.
- Programming education research on subgoal-labelled worked examples.
- PRIMM: Predict, Run, Investigate, Modify, Make.
- Programming traces and novice code-writing skills.
Final idea: Smith–Waterman is a lesson in disciplined forgetting. Dynamic programming is often described as remembering useful past work; here, the zero in the recurrence is equally important because it tells the algorithm when previous history has become harmful and should be discarded.
