Longest Spoken Prefix with Repeated Words: Review an LCS Version, Then Rewrite It

Read the full interview experience this question came from →

Quick Overview

A voice agent's transcript may repeat characters, words or phrases of its script but never skips or substitutes anything. You review a buggy longest-common-subsequence implementation of the longest spoken prefix, then rewrite it around the repetition-only guarantee, testing code review, string algorithms and careful reading of constraints.

Longest Spoken Prefix with Repeated Words: Review an LCS Version, Then Rewrite It

Company: Elevenlabs

Role: Software Engineer

Category: Software Engineering Fundamentals

Difficulty: medium

Interview Round: Onsite

A voice agent receives a script from a language model, `want_to_speak`, and produces a transcript of what it has actually said, `spoken_text`. The script is always correct. The transcript can contain repeated characters, repeated words or repeated word phrases, but speech only ever adds repetitions: the agent never skips or substitutes anything from the script. Return the longest prefix of `want_to_speak` that the agent has actually spoken. ```text want_to_speak: I can help you book an air ticket spoken_text: I can can help you book expected: I can help you book ``` ```text want_to_speak: I can help you book an air ticket spoken_text: I can can expected: I can ``` The round has two parts: first review a junior developer's implementation, then write your own version, `function_v2`. ### Clarifying Questions - Should the comparison be done word by word or character by character, given that a repetition can be a single stuttered character inside a word? - If the transcript ends in the middle of a word, does the partial word count as spoken? - Must case, punctuation and spacing match exactly, and should the result keep the script's original spacing? - What should happen when the script itself contains an immediately repeated word or phrase, such as "that that"? ### Part 1 — Review the LCS-based implementation The junior developer computes the longest common subsequence (LCS) of the two strings: a dynamic-programming table gives the LCS length, and the LCS is then rebuilt by walking the table from the bottom-right corner back to the start. The original code was not shared; the version below is a reconstruction of the described approach with the same two kinds of defect. Review it as you would a pull request. ```python def function_v1(want_to_speak: str, spoken_text: str) -> str: n, m = len(want_to_speak), len(spoken_text) dp = [[0] * m for _ in range(n)] for i in range(1, n + 1): for j in range(1, m + 1): if want_to_speak[i - 1] == spoken_text[j - 1]: dp[i][j] = dp[i - 1][j - 1] + 1 else: dp[i][j] = max(dp[i - 1][j], dp[i][j - 1]) # Rebuild the LCS from right to left. i, j, out = n, m, [] while i > 0 and j > 0: if want_to_speak[i - 1] == spoken_text[j - 1]: out.append(want_to_speak[i - 1]) i -= 1 j -= 1 elif dp[i - 1][j] >= dp[i][j - 1]: i -= 1 else: j -= 1 return "".join(reversed(out)) ``` Even once it stops crashing, this approach returns `"I can an"` for the second example instead of `"I can"`. ```hint Run it in your head Compare the table's size with the largest indices the loops touch. Then trace the second example and ask where in `want_to_speak` the final "an" of the wrong output comes from. ``` #### What This Part Should Cover - The indexing defect: what fails, on which inputs, and the fix - Why a longest common subsequence is not the longest spoken prefix, shown on the failing example - The time and memory cost of the table for long scripts and transcripts - Which tests would have caught both defects before review ### Part 2 — Implement `function_v2` Write `function_v2(want_to_speak: str, spoken_text: str) -> str` so that it returns the expected output for both examples above and relies on the guarantee that speech only adds repetitions. State its time and memory cost. ```hint Read the guarantee again If nothing is ever skipped or substituted, ask what it can mean when the next piece of the transcript differs from the next piece of the script you are waiting for. ``` #### What This Part Should Cover - A solution that exploits the repetition-only guarantee instead of a general alignment - The unit of comparison, and how stuttered characters inside a word are treated - Output that matches the examples exactly, including no trailing space - Inputs on which the chosen rule could still be fooled, and what you would ask about them ### What a Strong Answer Covers - Reads the problem statement closely and turns the repetition-only guarantee into the algorithm - Finds both defects in the review and explains them with a concrete trace - Time and memory analysis for both versions, with a rewrite that is asymptotically cheaper than the table - Tests for both examples, a repetition at the very start or end, an empty transcript, a transcript equal to the script, and a stutter inside a word - Names the remaining ambiguities and asks about them instead of guessing silently ### Follow-up Questions - The transcript arrives in small chunks while the agent is speaking. How do you keep the answer current without rescanning from the start? - The script is "I said that that is fine" and the agent says it exactly. What does your function return, and what if the agent had said "that" three times? - If the speech recognizer could also drop or mishear words, which approach would you switch to, and what would it cost? - The user interrupts the agent mid-sentence. How would the spoken prefix be used in the conversation that follows?

Overview: A voice agent's transcript may repeat characters, words or phrases of its script but never skips or substitutes anything. You review a buggy longest-common-subsequence implementation of the longest spoken prefix, then rewrite it around the repetition-only guarantee, testing code review, string algorithms and careful reading of constraints.

Read the full Elevenlabs Software Engineer interview experience this question came from

Elevenlabs logo
Elevenlabs
Nov 8, 2026
mediumSoftware EngineerOnsiteSoftware Engineering Fundamentals
0
0

A voice agent receives a script from a language model, want_to_speak, and produces a transcript of what it has actually said, spoken_text. The script is always correct. The transcript can contain repeated characters, repeated words or repeated word phrases, but speech only ever adds repetitions: the agent never skips or substitutes anything from the script. Return the longest prefix of want_to_speak that the agent has actually spoken.

want_to_speak: I can help you book an air ticket
spoken_text:   I can can help you book
expected:      I can help you book
want_to_speak: I can help you book an air ticket
spoken_text:   I can can
expected:      I can

The round has two parts: first review a junior developer's implementation, then write your own version, function_v2.

Clarifying Questions Guidance

  • Should the comparison be done word by word or character by character, given that a repetition can be a single stuttered character inside a word?
  • If the transcript ends in the middle of a word, does the partial word count as spoken?
  • Must case, punctuation and spacing match exactly, and should the result keep the script's original spacing?
  • What should happen when the script itself contains an immediately repeated word or phrase, such as "that that"?

Part 1 — Review the LCS-based implementation

The junior developer computes the longest common subsequence (LCS) of the two strings: a dynamic-programming table gives the LCS length, and the LCS is then rebuilt by walking the table from the bottom-right corner back to the start. The original code was not shared; the version below is a reconstruction of the described approach with the same two kinds of defect. Review it as you would a pull request.

def function_v1(want_to_speak: str, spoken_text: str) -> str:
    n, m = len(want_to_speak), len(spoken_text)
    dp = [[0] * m for _ in range(n)]
    for i in range(1, n + 1):
        for j in range(1, m + 1):
            if want_to_speak[i - 1] == spoken_text[j - 1]:
                dp[i][j] = dp[i - 1][j - 1] + 1
            else:
                dp[i][j] = max(dp[i - 1][j], dp[i][j - 1])

    # Rebuild the LCS from right to left.
    i, j, out = n, m, []
    while i > 0 and j > 0:
        if want_to_speak[i - 1] == spoken_text[j - 1]:
            out.append(want_to_speak[i - 1])
            i -= 1
            j -= 1
        elif dp[i - 1][j] >= dp[i][j - 1]:
            i -= 1
        else:
            j -= 1
    return "".join(reversed(out))

Even once it stops crashing, this approach returns "I can an" for the second example instead of "I can".

What This Part Should Cover Guidance

  • The indexing defect: what fails, on which inputs, and the fix
  • Why a longest common subsequence is not the longest spoken prefix, shown on the failing example
  • The time and memory cost of the table for long scripts and transcripts
  • Which tests would have caught both defects before review

Part 2 — Implement function_v2

Write function_v2(want_to_speak: str, spoken_text: str) -> str so that it returns the expected output for both examples above and relies on the guarantee that speech only adds repetitions. State its time and memory cost.

What This Part Should Cover Guidance

  • A solution that exploits the repetition-only guarantee instead of a general alignment
  • The unit of comparison, and how stuttered characters inside a word are treated
  • Output that matches the examples exactly, including no trailing space
  • Inputs on which the chosen rule could still be fooled, and what you would ask about them

What a Strong Answer Covers Guidance

  • Reads the problem statement closely and turns the repetition-only guarantee into the algorithm
  • Finds both defects in the review and explains them with a concrete trace
  • Time and memory analysis for both versions, with a rewrite that is asymptotically cheaper than the table
  • Tests for both examples, a repetition at the very start or end, an empty transcript, a transcript equal to the script, and a stutter inside a word
  • Names the remaining ambiguities and asks about them instead of guessing silently

Follow-up Questions Guidance

  • The transcript arrives in small chunks while the agent is speaking. How do you keep the answer current without rescanning from the start?
  • The script is "I said that that is fine" and the agent says it exactly. What does your function return, and what if the agent had said "that" three times?
  • If the speech recognizer could also drop or mishear words, which approach would you switch to, and what would it cost?
  • The user interrupts the agent mid-sentence. How would the spoken prefix be used in the conversation that follows?