Coding questions · Airbnb
Redact Document Phrases with Simultaneous Replacement
Redact document phrases with a replacement map, whole-word matching, longest-match overlap rules, and one-pass replacement of original text.
A document contains words or phrases that must be replaced using a supplied mapping. Perform all replacements against the original document so text inserted by one replacement is not processed again.
Implement redact_document(text: string, phrases: string[], replacements: string[]) -> string. The two arrays have equal length; phrases[i] maps to replacements[i].
Constraints & Assumptions
- Matching is case-sensitive and literal, including internal spaces.
- For this practice version, a match must have whole-word boundaries. Word characters are ASCII letters, digits, and underscore; the characters immediately before and after a match, if present, must not be word characters.
- Phrases are distinct, nonempty, and begin and end with a word character. Replacement strings may be empty and are inserted verbatim.
- Scan the original text left to right. At each position with one or more valid matches, choose the longest phrase, emit its replacement, and continue after the matched original span. Distinct phrases of equal length cannot both exactly match the same span.
- If no phrase matches at a position, preserve the original character.
- Boundary, overlap-priority, and simultaneous-replacement rules are explicit practice choices; the source gives the replacement-map task but does not specify these edge cases.
- All text is ASCII. Text length is at most 10,000, there are at most 100 phrases, and each phrase and replacement has at most 100 characters.
Examples
text = "Person One emailed Person."
phrases = ["Person","Person One"]
replacements = ["word","name"]
result = "name emailed word."
text = "red redwood blue"
phrases = ["red","blue"]
replacements = ["blue",""]
result = "blue redwood "
The inserted blue is not redacted again, and red does not match inside redwood.
Hint: Separate original positions from output
Advance through the input according to the length of the original matched phrase. Appending replacement text should not change which source characters are considered next.
Replace Whole Phrases Simultaneously with Longest-Match Priority
Approach
Keep a cursor into the original text and a separate output builder. At each cursor, first test the left whole-word boundary in the original text. Examine candidate phrases with literal case-sensitive prefix comparison and test their original right boundary. Among valid matches retain the longest; distinct equal-length phrases cannot tie on one span. If a match exists, append its mapped replacement verbatim and skip the entire original phrase. Otherwise append exactly the current original character and advance one. This follows the prescribed left-to-right choice, prevents overlapping consumed spans, and never exposes inserted output to later matching or boundary tests. ASCII letters, digits and underscore are the only word characters; internal phrase spaces and punctuation are literal. For text length T, M phrases and maximum phrase length L, the straightforward bounded algorithm takes O(TML + output length) worst-case time. Output builders and Python/JavaScript piece lists use O(T+output length) space; aside from those buffers, selection state is constant. A trie could reduce repeated prefix comparisons for much larger vocabularies, but the stated limits permit this direct implementation.
- Time complexity: O(T * M * L + output length)
- Space complexity: O(T + output length) including builders and piece lists