Highlight Exact Source Phrases and Attach Citations
You are given a text string and an indexed list of source phrases. All input tokens are alphanumeric and separated by single spaces. A source matches only as a sequence of whole words; for example, network does not match networking.
Implement both stages below.
Stage 1 - Merged Highlights
Find every exact occurrence of every source phrase. Convert each occurrence to a half-open word interval. Merge intervals that overlap; do not merge intervals separated by one or more unmatched words. Wrap each merged interval in <yellow> and </yellow> tags.
Example:
text = "the quick brown fox"
sources = ["the quick", "quick brown"]
result = "<yellow>the quick brown</yellow> fox"
The two source occurrences overlap at quick, so they form one properly nested highlight rather than crossing tags.
Stage 2 - Citation Ordering
After each merged highlight, append one citation [i] for every distinct source index with at least one occurrence overlapping that highlight.
Order those citation indices by:
-
The source's total number of occurrences across the entire input text, descending.
-
Source index ascending when total counts tie.
Repeated occurrences of one source inside the same merged region still produce that source's citation only once for that region.
Example:
text = "brown v board changed law brown v board"
sources = ["brown v board changed", "brown v board", "changed law"]
Source 1 occurs twice; sources 0 and 2 occur once. The first merged region therefore ends with citations in the order [1][0][2]. The second region has only [1].
Function Contract
highlight_with_citations(text, sources) -> string
Return the Stage 2 result, including tags and citations. If there are no matches, return text unchanged.
Constraints
-
0 <= number of words in text <= 10000
-
0 <= len(sources) <= 1000
-
Every source contains at least one word.
-
A source may occur multiple times, including overlapping with itself.
-
Duplicate source strings at different indices remain distinct citation sources.
-
Matching is case-sensitive.
Hints
-
Tokenize once and record occurrences as
(start, end, source_index)
.
-
Sort intervals by start position, then merge while retaining the set of contributing source indices.
-
Compute global occurrence counts before rendering citations.
-
Render from the word sequence so tags never split a word.
Discussion Extensions
-
Analyze the straightforward matching complexity and suggest an approach for many source phrases.
-
How would punctuation and original whitespace preservation change tokenization and rendering?
-
What behavior would you choose for adjacent, non-overlapping highlights?