AlgoMaster Logo

Word Pattern

Last Updated: March 29, 2026

easy

Understanding the Problem

We're given a pattern like "abba" and a sentence like "dog cat cat dog". The question is whether there's a one-to-one correspondence between letters in the pattern and words in the sentence. 'a' always maps to the same word, 'b' always maps to the same word, and no two different letters map to the same word.

The tricky part is that the mapping must be bijective, meaning it goes both ways. It's not enough for each letter to consistently map to the same word. We also need each word to consistently map to the same letter. For example, pattern "ab" and string "dog dog" should return false because both 'a' and 'b' would map to "dog", violating the bijection.

So the key observation is: we need to track two mappings simultaneously. One from characters to words, and another from words to characters. If either mapping is violated, the answer is false.

Key Constraints:

  • 1 <= pattern.length <= 300 -- The pattern is very small. Even O(n^2) would be fine, but O(n) is natural here.
  • 1 <= s.length <= 3000 -- The string is also small. No need to worry about performance at all.
  • pattern contains only lowercase English letters -- At most 26 distinct characters. A fixed-size array could work for the char-to-word mapping.
  • Words are separated by single spaces with no leading/trailing spaces -- Splitting on space is straightforward, no edge cases with whitespace.

Approach 1: Two Hash Maps (Bijection Check)

Intuition

The most natural approach: walk through the pattern and words in parallel, maintaining a mapping in both directions.

When we see a pattern character and a word together for the first time, we create a bidirectional mapping. If we see them again, we verify the existing mapping still holds. If a character was previously mapped to a different word, or a word was previously mapped to a different character, the bijection is broken.

Why two maps? Because a single map only enforces one direction. If we only track char-to-word, pattern "ab" with "dog dog" would incorrectly pass: 'a' -> "dog" is fine, and 'b' -> "dog" doesn't conflict with any existing mapping in a char-to-word map. But it violates the bijection because "dog" is now mapped to two different characters. The word-to-char map catches this.

Algorithm

  1. Split the string s into an array of words.
  2. If the number of words doesn't equal the length of pattern, return false.
  3. Create two hash maps: charToWord (character -> string) and wordToChar (string -> character).
  4. For each index i, get the current pattern character and the current word.
  5. If the character already has a mapping in charToWord, check that it maps to the current word. If not, return false.
  6. If the word already has a mapping in wordToChar, check that it maps to the current character. If not, return false.
  7. If neither mapping exists, create both mappings.
  8. If we get through all positions without conflict, return true.

Example Walkthrough

1Initialize: split words, check lengths match (4 == 4)
0
a
i=0
1
b
2
b
3
a
1/6
1Both maps empty
1/6

Code

This approach works well and directly models the bijection. But what if instead of tracking explicit mappings, we just encoded the structure of each sequence and compared the encodings directly?

Approach 2: Index Mapping (Single-Pass Structure Comparison)

Intuition

Two sequences follow the same pattern if and only if they have the same "first occurrence" structure. Consider pattern "abba": the first occurrence indices are [0, 1, 1, 0], because 'a' first appears at index 0, 'b' first appears at index 1, 'b' was already seen at index 1, and 'a' was already seen at index 0. If the words "dog cat cat dog" produce the same structure [0, 1, 1, 0], the pattern matches.

This approach avoids the explicit bijection check entirely. Instead of asking "does the mapping hold in both directions?", we ask "do both sequences have the same structural fingerprint?"

Algorithm

  1. Split s into words. If the count doesn't match pattern length, return false.
  2. For each position, record the first occurrence index of the pattern character and the first occurrence index of the word.
  3. If at any position the first-occurrence indices differ between the pattern and the words, return false.
  4. If all positions match, return true.

Example Walkthrough

1Initialize: compare first-occurrence indices
0
a
i=0
1
b
2
b
3
a
1/6
1Track first occurrence index for each char
1/6

Code