Add ? to make a quantifier minimal-match
To flip greedy → lazy, append ? to the quantifier:
*?— 0 or more, but as few as possible+?— 1 or more, but as few as possible??— 0 or 1, prefer 0{n,m}?— between n and m, prefer n
Lazy quantifiers consume the MINIMUM and only extend if the rest of the pattern fails. Backwards from greedy, but same backtracking machinery.
The HTML disaster, fixed
Greedy .* ate both <p> blocks as one match. Lazy .*? matches each one separately — it stops at the first </p> instead of the last.
Performance note
Lazy is not free. The engine still backtracks; it just backtracks in the opposite direction (extending instead of shrinking). For some patterns lazy is faster, for others greedy is. The bigger win is correctness — lazy matches what you usually want.
The negated-class alternative
Often the cleanest fix is neither lazy nor greedy: it's a negated class. <p>([^<]*)</p> says "capture everything that's NOT a <" — no backtracking, no surprise. Track 8 will show this is the secret to ReDoS-safe patterns.