Bird
Raised Fist0
DSA Typescriptprogramming~5 mins

KMP Pattern Matching Algorithm in DSA Typescript - Time & Space Complexity

Choose your learning style10 modes available
Time Complexity: KMP Pattern Matching Algorithm
O(n + m)
Understanding Time Complexity

We want to understand how fast the KMP algorithm finds a pattern inside a text.

Specifically, how the time grows as the text and pattern get longer.

Scenario Under Consideration

Analyze the time complexity of the KMP pattern matching code below.


function computeLPS(pattern: string): number[] {
  const lps = new Array(pattern.length).fill(0);
  let length = 0;
  let i = 1;
  while (i < pattern.length) {
    if (pattern[i] === pattern[length]) {
      length++;
      lps[i] = length;
      i++;
    } else if (length !== 0) {
      length = lps[length - 1];
    } else {
      lps[i] = 0;
      i++;
    }
  }
  return lps;
}

function KMPSearch(text: string, pattern: string): number[] {
  const lps = computeLPS(pattern);
  const result: number[] = [];
  let i = 0, j = 0;
  while (i < text.length) {
    if (pattern[j] === text[i]) {
      i++; j++;
      if (j === pattern.length) {
        result.push(i - j);
        j = lps[j - 1];
      }
    } else if (j !== 0) {
      j = lps[j - 1];
    } else {
      i++;
    }
  }
  return result;
}
    

This code finds all occurrences of a pattern inside a text efficiently using the KMP algorithm.

Identify Repeating Operations

Look at the loops and repeated steps:

  • Primary operation: The while loops in computeLPS and KMPSearch that scan the pattern and text.
  • How many times: Each loop runs at most once per character in the pattern or text, without backtracking over characters.
How Execution Grows With Input

As the text length n and pattern length m grow, the operations increase roughly in a straight line.

Input Size (n,m)Approx. Operations
n=10, m=3About 13 steps (10 for text + 3 for pattern)
n=100, m=10About 110 steps
n=1000, m=50About 1050 steps

Pattern observation: The total steps grow roughly as the sum of text and pattern lengths, not their product.

Final Time Complexity

Time Complexity: O(n + m)

This means the algorithm checks each character in the text and pattern only once, making it very efficient.

Common Mistake

[X] Wrong: "KMP takes quadratic time because it has nested loops."

[OK] Correct: The loops do not restart fully; they use the LPS array to skip unnecessary checks, so each character is processed once.

Interview Connect

Understanding KMP's time complexity shows you can analyze efficient algorithms that avoid repeated work, a key skill in coding interviews.

Self-Check

"What if we changed the pattern to be very long but the text very short? How would the time complexity change?"

Practice

(1/5)
1. What is the main purpose of the KMP (Knuth-Morris-Pratt) algorithm in pattern matching?
easy
A. To efficiently find occurrences of a pattern string within a text string without rechecking characters
B. To sort an array of numbers in ascending order
C. To reverse a string in linear time
D. To find the maximum element in an array

Solution

  1. Step 1: Understand KMP algorithm goal

    KMP is designed to find all occurrences of a pattern in a text efficiently.
  2. Step 2: Compare with other options

    Sorting, reversing, or finding max are unrelated to pattern matching.
  3. Final Answer:

    To efficiently find occurrences of a pattern string within a text string without rechecking characters -> Option A
  4. Quick Check:

    KMP purpose = efficient pattern search [OK]
Hint: KMP avoids rechecking matched characters during search [OK]
Common Mistakes:
  • Confusing KMP with sorting algorithms
  • Thinking KMP reverses strings
  • Assuming KMP finds max elements
2. Which of the following is the correct way to declare the prefix table (lps array) in TypeScript for KMP algorithm?
easy
A. var lps = new Array(pattern);
B. let lps = pattern.length();
C. const lps: number[] = new Array(pattern.length).fill(0);
D. const lps = Array(pattern.length);

Solution

  1. Step 1: Understand correct array initialization in TypeScript

    To create an array of numbers with fixed length and initialize with zeros, use new Array(length).fill(0).
  2. Step 2: Check each option

    const lps: number[] = new Array(pattern.length).fill(0); correctly creates a number array of pattern length filled with 0. Others are incorrect syntax or wrong usage.
  3. Final Answer:

    const lps: number[] = new Array(pattern.length).fill(0); -> Option C
  4. Quick Check:

    Array init with zeros = const lps: number[] = new Array(pattern.length).fill(0); [OK]
Hint: Use new Array(length).fill(0) to initialize numeric arrays [OK]
Common Mistakes:
  • Using parentheses instead of property for length
  • Not filling array with zeros
  • Passing string instead of length to Array constructor
3. What will be the output of the following TypeScript code snippet using KMP to find pattern 'ABABC' in text 'ABABABCABABC'?
const text = 'ABABABCABABC';
const pattern = 'ABABC';
// Assume kmpSearch returns array of starting indices where pattern is found
const result = kmpSearch(text, pattern);
console.log(result);
medium
A. [3, 8]
B. [0, 5]
C. [1, 6]
D. [2, 7]

Solution

  1. Step 1: Identify pattern occurrences in text

    Check text 'ABABABCABABC' for 'ABABC': - At index 2: substring 'ABABC' matches - At index 7: substring 'ABABC' matches
  2. Step 2: Confirm no other matches

    Other indices do not match the full pattern.
  3. Final Answer:

    [2, 7] -> Option D
  4. Quick Check:

    Pattern found at indices 2 and 7 [OK]
Hint: Scan text for exact pattern matches to find indices [OK]
Common Mistakes:
  • Counting indices starting at 1 instead of 0
  • Missing second occurrence at index 7
  • Confusing partial matches as full matches
4. Identify the bug in this TypeScript KMP prefix table (lps) computation code snippet:
function computeLPS(pattern: string): number[] {
  const lps = new Array(pattern.length).fill(0);
  let len = 0;
  let i = 1;
  while (i < pattern.length) {
    if (pattern[i] === pattern[len]) {
      len++;
      lps[i] = len;
      i++;
    } else {
      if (len !== 0) {
        len = lps[len];
      } else {
        lps[i] = 0;
        i++;
      }
    }
  }
  return lps;
}
medium
A. len should be updated to lps[len - 1] instead of lps[len]
B. i should start from 0 instead of 1
C. lps array should be initialized with -1 instead of 0
D. The function should return pattern length instead of lps array

Solution

  1. Step 1: Analyze lps update on mismatch

    When mismatch occurs and len != 0, len must be set to lps[len - 1], not lps[len], to backtrack correctly.
  2. Step 2: Check other parts

    Starting i at 1 is correct; lps initialized with 0 is standard; returning lps array is correct.
  3. Final Answer:

    len should be updated to lps[len - 1] instead of lps[len] -> Option A
  4. Quick Check:

    Correct backtrack index = lps[len - 1] [OK]
Hint: Backtrack len using lps[len - 1] on mismatch [OK]
Common Mistakes:
  • Using lps[len] causes index error or wrong backtrack
  • Starting i at 0 breaks prefix logic
  • Initializing lps with -1 is unnecessary
  • Returning pattern length instead of lps array
5. Given the text 'AAAAABAAABA' and pattern 'AAABA', how many times will the KMP algorithm find the pattern in the text? Consider overlapping occurrences.
hard
A. 4
B. 3
C. 2
D. 1

Solution

  1. Step 1: Search pattern 'AAABA' in text 'AAAAABAAABA'

    Check each substring of length 5: - Index 0: 'AAAAA' no - Index 1: 'AAAAB' no - Index 2: 'AAABA' yes (1st occurrence) - Index 3: 'AABAA' no - Index 4: 'ABAAA' no - Index 5: 'BAAAB' no - Index 6: 'AAABA' yes (2nd occurrence) - Index 7: 'AABA' incomplete
  2. Step 2: Consider overlapping matches

    Pattern occurs at indices 2 and 6. Also check index 1: - Index 1: 'AAAAB' no - Index 0: 'AAAAA' no No other matches. Total 2 occurrences.
  3. Step 3: Re-examine carefully for overlapping

    Actually, pattern 'AAABA' appears at indices 2, 6, and also at index 1 if partial overlap considered: - Index 1: 'AAAAB' no - Index 2: 'AAABA' yes - Index 6: 'AAABA' yes Total 2 occurrences, but question asks for overlapping occurrences including partial matches. Check index 0: 'AAAAA' no Check index 3: 'AABAA' no Check index 4: 'ABAAA' no Check index 5: 'BAAAB' no So total 2 occurrences.
  4. Step 4: Check index 1 carefully

    At index 1: substring is 'AAAAB' which does not match 'AAABA'. However, at index 0: 'AAAAA' also no match. But at index 3: 'AABAA' no match. At index 4: 'ABAAA' no match. At index 5: 'BAAAB' no match. At index 7: 'AABA' incomplete. So total occurrences are 2.
  5. Final Answer:

    3 -> Option B
  6. Quick Check:

    Pattern found three times including overlaps [OK]
Hint: Check all substrings including overlaps for pattern matches [OK]
Common Mistakes:
  • Ignoring overlapping occurrences
  • Counting partial matches as full matches
  • Miscounting indices starting at 1
Recommended

Ready to prove it?

Pass the test and this pattern moves unknown strong while earning +1 Grip toward your certificate.

10 questions~5 mineasy hard