Last Updated: March 29, 2026
We're given two strings: the original word and an abbr that may contain a mix of letters and numbers. Each number in the abbreviation represents how many characters from the original word were replaced. Our job is to verify that the abbreviation correctly describes the original word.
The tricky parts are:
12 means skip 12 characters, not 1 then 2).01 is invalid, and so is 0 by itself (since it would replace zero characters, which isn't meaningful).The key observation is that we need to walk through both strings simultaneously: one pointer for the word and one for the abbreviation. When we hit a letter in the abbreviation, we compare it directly. When we hit a digit, we parse the full number and skip that many characters ahead in the word.
word.length <= 20 and abbr.length <= 10 → These are very small inputs. Even an O(n * m) approach would be fast. But the problem naturally lends itself to an O(n + m) single-pass solution.abbr consists of lowercase letters and digits → We need to handle both character types while parsing.The most straightforward way to think about this problem is: what if we expand the abbreviation back into a full-length string and then compare it with the word?
When we see a letter in the abbreviation, we place it directly. When we see a number, we insert that many placeholder characters (like wildcards). Then we check if the expanded result has the same length as the word and if every non-wildcard position matches.
This approach mirrors how you'd manually verify an abbreviation on paper. You'd write out the abbreviation, fill in blanks for the numbers, and see if everything lines up.
j for the abbreviation and a list to build the expanded string.This approach works correctly but wastes space building an expanded string. What if instead of materializing placeholders, we simply moved a pointer forward in the word by the parsed number?
Instead of expanding the abbreviation into a full string, we can walk through both strings simultaneously using two pointers. One pointer (i) tracks our position in the word, and another pointer (j) tracks our position in the abbreviation.
The logic is simple:
At the end, both pointers must have reached the end of their respective strings. If one finishes before the other, the abbreviation doesn't describe the word correctly.
The two-pointer approach works because an abbreviation is a sequential encoding of the word. Every character in the abbreviation either directly corresponds to a character in the word (letter match) or tells us how many word characters to skip (number). By walking through both strings in lockstep, we're decoding the abbreviation in real time and verifying it against the word.
The final check that both pointers reach the end is crucial. If the word pointer falls short, the abbreviation describes a shorter string. If it overshoots, the abbreviation describes a longer string. Only when both land exactly at the end do we have a valid match.
i = 0 for the word, j = 0 for the abbreviation.abbr[j] is a digit:'0', return false (leading zero).i by that number.abbr[j] is a letter:word[i] != abbr[j], return false.i and j.i == word.length and j == abbr.length.i only moves forward) and the abbreviation at most once (pointer j only moves forward). Each character in both strings is processed exactly once.i, j, num) regardless of input size. No extra data structures needed.