← DoorDash Interview Insights

DoorDash·Software Engineer·Technical Phone Screen·Senior

SeniorPrefer not to say
Jul 2026Remote

Summary

DoorDash software engineering interview that went deep on string search algorithms. The main problem was KMP-style pattern matching and then they kept pulling the thread with follow-ups for a solid chunk of the session. More theoretical than I expected for a product company.

Questions Asked (6)

Q1

Implement a function that finds the first occurrence of a pattern string inside a text string, returning the starting index or -1 if not found. Target linear time relative to the combined lengths and space proportional to the pattern.

Algorithms & Data Structures
Author's notes

I knew this was KMP territory immediately but my failure table construction was shaky under pressure.

Create a free account to read the full note

AI HintsAI Generated

Suggested Approach

Clarify the requirements and constraints, then propose the KMP algorithm as the optimal solution. Explain how the prefix function (LPS array) enables linear-time matching by avoiding redundant comparisons, and walk through a small example to demonstrate correctness and complexity.

Pro tip: Mention that while KMP is optimal, simpler algorithms like Boyer-Moore or Rabin-Karp might be preferred in practice depending on the input characteristics, showing awareness of trade-offs. Also, explicitly state that you would handle edge cases like empty pattern or pattern longer than text.

1. Clarify requirements and constraints

Ask about input types, expected time/space complexity, and edge cases (e.g., empty pattern, pattern longer than text). Confirm that linear time and space proportional to pattern are hard requirements.

2. Choose the algorithm

Select KMP as it meets the complexity requirements. Briefly explain why naive O(n*m) is insufficient and why KMP's preprocessing of the pattern allows linear-time search.

3. Explain the prefix function (LPS array)

Describe how to compute the longest proper prefix that is also a suffix for each position in the pattern. Show how this array is used to skip characters during matching without backtracking in the text.

4. Walk through the matching process

Illustrate the two-pointer technique: iterate through text and pattern, using the LPS array to shift the pattern when a mismatch occurs. Provide a small example to demonstrate.

5. Analyze complexity and edge cases

State that time is O(n+m) and space is O(m). Discuss handling of empty pattern (return 0) and pattern longer than text (return -1).

Key Points to Mention

  • KMP algorithm and its linear time complexity
  • Prefix function (LPS array) construction and purpose
  • Avoiding redundant comparisons by not backtracking in text
  • Time complexity O(n+m) and space complexity O(m)
  • Edge cases: empty pattern, pattern longer than text, no match
  • Comparison with other algorithms (e.g., naive, Rabin-Karp, Boyer-Moore)

AI-generated suggestions, not part of the candidate's original notes. May be inaccurate — verify before relying on them.

Q2

Compare the naive brute-force approach, KMP, and Rabin-Karp for string matching. Walk through the time and space complexity of each and explain when you'd pick one over another.

Algorithms & Data StructuresTechnical Trade-offs
Author's notes

This part I actually felt okay about.

Create a free account to read the full note

AI HintsAI Generated

Suggested Approach

Start by defining the string matching problem and then systematically compare the three algorithms in terms of time and space complexity, highlighting their key ideas and trade-offs. Use a concrete example or two to illustrate worst-case scenarios, and conclude with practical guidance on when to choose each algorithm, tying it to real-world constraints like input size, alphabet, and expected patterns.

Pro tip: Mention that in practice, for most text search tasks, built-in library functions (like Python's `str.find` or C++'s `std::string::find`) often use optimized algorithms like Boyer-Moore or Two-Way, so knowing when to implement your own is key. Also, emphasize that Rabin-Karp's rolling hash makes it ideal for multiple pattern matching, while KMP guarantees linear time without hashing overhead.

1. Define the problem and baseline

Briefly state the string matching problem: finding all occurrences of a pattern P in a text T. Introduce the naive brute-force approach: check every possible alignment and compare characters one by one.

2. Analyze naive brute-force

State time complexity: O((n-m+1)*m) worst-case, often simplified to O(n*m), where n = |T|, m = |P|. Space complexity: O(1). Mention that it's simple but inefficient for repetitive patterns (e.g., T = 'aaaaa', P = 'aaa').

3. Explain KMP

Describe KMP's key idea: preprocess the pattern to build an LPS (longest proper prefix which is also suffix) array to avoid redundant comparisons. Time complexity: O(n + m) for preprocessing and matching. Space complexity: O(m) for the LPS array. Highlight that it guarantees linear time even in worst-case scenarios.

4. Explain Rabin-Karp

Describe Rabin-Karp's use of rolling hash to compare pattern and substring hashes in O(1) per shift. Time complexity: average O(n + m), worst-case O(n*m) due to hash collisions (though can be mitigated with good hash). Space complexity: O(1) (or O(m) if storing hashes). Mention its suitability for multiple pattern matching (e.g., plagiarism detection).

5. Compare and give selection criteria

Summarize trade-offs: Naive is simple but slow; KMP is optimal for single pattern with guaranteed linear time; Rabin-Karp is good for multiple patterns or when hashing is cheap. Discuss factors: input size, pattern length, alphabet size, need for worst-case guarantees, and implementation complexity.

Key Points to Mention

  • Time and space complexity of each algorithm: Naive O(n*m) time, O(1) space; KMP O(n+m) time, O(m) space; Rabin-Karp average O(n+m) time, worst-case O(n*m) time, O(1) space.
  • KMP's LPS array and how it enables skipping characters without re-comparing.
  • Rabin-Karp's rolling hash technique and its efficiency for multiple pattern searches.
  • Worst-case scenarios: Naive and Rabin-Karp degrade on repetitive patterns or hash collisions; KMP remains linear.
  • Practical considerations: implementation complexity, constant factors, and when to use built-in functions.
  • Use cases: KMP for single pattern in large text; Rabin-Karp for multiple patterns or when hashing is beneficial; Naive for small inputs or simplicity.

AI-generated suggestions, not part of the candidate's original notes. May be inaccurate — verify before relying on them.

Q3

How would you handle Unicode text and very large inputs in a string matching implementation? Think about both correctness and memory.

Algorithms & Data StructuresTechnical Trade-offs
Author's notes

Blanked for a second here.

Create a free account to read the full note

AI HintsAI Generated

Suggested Approach

Start by clarifying the requirements: what 'Unicode text' means (code points vs. grapheme clusters) and what 'very large inputs' implies (streaming vs. in-memory). Then propose a solution that normalizes Unicode to a canonical form and uses a streaming algorithm like KMP or Rabin-Karp with a sliding window to handle large inputs in O(1) memory relative to input size.

Pro tip: Mention that you would normalize both the pattern and text to the same Unicode normalization form (e.g., NFC) before matching, and use a streaming approach with a fixed-size buffer to avoid loading the entire input into memory. This shows you understand real-world data pitfalls and memory constraints.

1. Clarify requirements and constraints

Ask whether the input is a stream or a file, whether Unicode normalization is needed, and what the expected pattern length is. This determines the algorithm and memory strategy.

2. Handle Unicode correctly

Normalize both pattern and text to a consistent form (e.g., NFC) and decide whether to match on code points or grapheme clusters. Use a library that supports Unicode-aware operations.

3. Choose a streaming algorithm

Select an algorithm like KMP or Rabin-Karp that can process the text in chunks with a sliding window, maintaining only the necessary state (e.g., failure function or rolling hash).

4. Manage memory and I/O

Read the input in fixed-size buffers, process each chunk, and handle overlaps between chunks. Avoid storing the entire text; only keep the pattern and a small buffer.

5. Discuss trade-offs and edge cases

Compare time/space complexity, mention worst-case scenarios (e.g., repetitive patterns), and address how to handle partial matches at buffer boundaries.

Key Points to Mention

  • Unicode normalization (NFC, NFD, etc.) and its impact on matching
  • Difference between code points, code units, and grapheme clusters
  • Streaming algorithms (KMP, Rabin-Karp) and their memory characteristics
  • Buffer management and handling overlaps between chunks
  • Time and space complexity trade-offs (e.g., O(n) time, O(m) space for KMP)
  • Edge cases: empty pattern, pattern longer than buffer, invalid Unicode sequences

AI-generated suggestions, not part of the candidate's original notes. May be inaccurate — verify before relying on them.

Q4

Walk through the important edge cases for string matching: empty pattern, empty text, pattern longer than text, and highly repetitive patterns.

Algorithms & Data Structures
Author's notes

Fine.

Create a free account to read the full note

AI HintsAI Generated

Suggested Approach

Start by defining the string matching problem and then systematically walk through each edge case, explaining how a typical algorithm (like KMP or Rabin-Karp) would handle it. For each case, discuss the expected behavior, potential pitfalls, and how to ensure correctness and efficiency.

Pro tip: Relate the edge cases to real-world scenarios at DoorDash, such as searching for order IDs or restaurant names, to show practical awareness. Also, mention that handling these cases upfront can prevent runtime errors and improve performance.

1. Define the problem and assumptions

Clarify what string matching entails (e.g., finding a pattern in a text) and state assumptions about input types, character sets, and expected outputs.

2. Empty pattern

Discuss that an empty pattern matches at every position (including before the first character and after the last). Explain how algorithms should handle this to avoid infinite loops or incorrect matches.

3. Empty text

Explain that if the text is empty, the only possible match is if the pattern is also empty. Otherwise, no match. Mention that algorithms should quickly return without errors.

4. Pattern longer than text

State that if the pattern length exceeds the text length, no match is possible. Algorithms should check lengths early to avoid unnecessary work.

5. Highly repetitive patterns

Discuss how patterns like 'aaaaa' or 'ababab' can cause naive algorithms to degrade to O(n*m) due to many partial matches. Explain how KMP's failure function or Rabin-Karp's rolling hash mitigates this.

Key Points to Mention

  • Empty pattern matches at every position, including boundaries; some libraries return all indices, others return 0.
  • Empty text with non-empty pattern returns no match; empty text with empty pattern returns a match at index 0.
  • Pattern longer than text: immediate no-match; check lengths before processing.
  • Highly repetitive patterns cause worst-case behavior in naive search; use KMP or Rabin-Karp for linear time.
  • Edge cases affect algorithm choice and implementation details (e.g., loop bounds, hash collisions).
  • Testing edge cases is crucial; mention unit tests for these scenarios.

AI-generated suggestions, not part of the candidate's original notes. May be inaccurate — verify before relying on them.

Q5

Extend the pattern matcher to support wildcard characters where '?' matches any single character and '*' matches any sequence of zero or more characters. Describe how the semantics work and what the complexity looks like.

Algorithms & Data StructuresTechnical Trade-offs
Author's notes

This one hurt.

Create a free account to read the full note

AI HintsAI Generated

Suggested Approach

Start by clarifying the semantics of '?' and '*' with examples, then present a dynamic programming solution that builds a table of match results for prefixes. Discuss time and space complexity, and mention optimizations like two-pointer greedy or rolling arrays.

Pro tip: Explicitly state that '*' can match zero characters and that patterns like 'a**b' are valid, showing attention to edge cases. Also, briefly compare DP with greedy approaches to demonstrate trade-off awareness.

1. Clarify Semantics

Define how '?' matches exactly one character and '*' matches zero or more characters, including examples like 'a*b' matching 'ab', 'acb', 'axxb'.

2. Choose an Approach

Select dynamic programming for clarity and correctness, or a two-pointer greedy method for O(1) space, and justify the choice based on constraints.

3. Define DP Recurrence

Let dp[i][j] be true if first i characters of string match first j characters of pattern. Derive transitions for '?', '*', and literal characters.

4. Analyze Complexity

State time complexity O(m*n) and space complexity O(m*n), then mention space optimization to O(n) using rolling arrays.

5. Discuss Edge Cases and Optimizations

Cover empty string/pattern, consecutive '*', and mention greedy two-pointer approach with backtracking for O(m+n) time and O(1) space.

Key Points to Mention

  • DP recurrence: dp[i][j] = dp[i-1][j-1] if pattern[j-1] is '?' or matches string[i-1]; if pattern[j-1] is '*', dp[i][j] = dp[i][j-1] (zero chars) or dp[i-1][j] (one or more chars).
  • Base cases: dp[0][0] = true; dp[0][j] = dp[0][j-1] if pattern[j-1] is '*', else false; dp[i][0] = false for i>0.
  • Time complexity O(m*n) and space complexity O(m*n) for DP, with O(n) space optimization using rolling arrays.
  • Greedy two-pointer approach: iterate with pointers, use backtracking for '*' to achieve O(m+n) time and O(1) space.
  • Edge cases: empty string, empty pattern, pattern with only '*', consecutive '*' characters.
  • Trade-offs: DP is simpler to reason about but uses more space; greedy is more efficient but trickier to implement correctly.

AI-generated suggestions, not part of the candidate's original notes. May be inaccurate — verify before relying on them.

Q6

Extend the solution to search for multiple patterns simultaneously in a single pass over the text and return all match positions for each pattern. What data structure would you use and how does the runtime compare to running single-pattern search once per pattern?

Algorithms & Data StructuresSystem Design
Author's notes

I said Aho-Corasick and explained the trie-plus-failure-links structure at a high level.

Create a free account to read the full note

AI HintsAI Generated

Suggested Approach

First, clarify the problem constraints (e.g., number of patterns, pattern lengths, alphabet size) and discuss the trade-offs between different multi-pattern search algorithms. Then, propose a suitable data structure like a trie or Aho-Corasick automaton, explain how it enables a single pass over the text, and analyze the runtime complexity compared to running single-pattern searches sequentially.

Pro tip: Mention that Aho-Corasick is the standard solution for this problem and that it's used in real-world systems like intrusion detection and plagiarism detection. Also, note that while the asymptotic runtime is often better, the constant factors and preprocessing time matter in practice.

1. Clarify requirements and constraints

Ask about the number of patterns, their lengths, the size of the text, and whether patterns can overlap or contain each other. This helps determine the most efficient approach.

2. Choose the right data structure

Propose building a trie of all patterns and augmenting it with failure links to form an Aho-Corasick automaton. This allows simultaneous matching of all patterns in a single pass.

3. Explain the algorithm

Describe how the automaton processes each character of the text, following goto, failure, and output links to report matches. Emphasize that each character is processed in O(1) amortized time.

4. Analyze runtime and compare

State that the total time is O(|text| + sum of pattern lengths + number of matches) for Aho-Corasick, versus O(k * |text|) for running k separate single-pattern searches (e.g., KMP each). Highlight the improvement when k is large.

5. Discuss trade-offs and alternatives

Mention that preprocessing time and memory for the automaton may be higher, and that for very few patterns, separate searches might be simpler. Also, note other approaches like suffix automata or Rabin-Karp for multiple patterns.

Key Points to Mention

  • Aho-Corasick automaton: trie with failure links and output links
  • Single pass over text: O(|text|) time for matching, plus O(total pattern length) preprocessing
  • Comparison: O(|text| + sum|patterns| + matches) vs O(k * |text|) for k separate searches
  • Handling overlapping patterns and reporting all match positions
  • Space complexity: O(sum|patterns| * alphabet size) for the automaton
  • Real-world applications: intrusion detection, keyword highlighting, DNA sequence analysis

AI-generated suggestions, not part of the candidate's original notes. May be inaccurate — verify before relying on them.