Problem
Given a pattern
and a string s
, find if s
follows the same pattern.
Here follow means a full match, such that there is a bijection between a letter in pattern
and a non-empty word in s
.
Examples
Example 1:
Input:
pattern = "abba", s = "dog cat cat dog"
Output:
true
Example 2:
Input:
pattern = "abba", s = "dog cat cat fish"
Output:
false
Example 3:
Input:
pattern = "aaaa", s = "dog cat cat dog"
Output:
false
Solution
Method 1 - Using 2 Hash tables
This problem is similar to Isomorphic Strings Problem. We create 2 hashtables from pattern to str and str to pattern.
Why We Need 2 Hashmaps?
Consider the string [a b b a]
→ [dog cat cat dog]
; In this case 1 hashmap from pattern to str is enough. But suppose we have [a b b c]
→ [dog cat cat dog]
. If we just use one hashmap, we will return true. So, important is dog should also match to a
and not c
.
Code
Java
public boolean wordPattern(String pattern, String str) {
String[] words = str.split(" ");
if (words.length != pattern.length()) {
return false;
}
Map<String, Character> wordToChar = new HashMap<>();
Map<Character, String> charToWord = new HashMap<>();
for (int i = 0; i < words.length; i++) {
String word = words[i];
char c = pattern.charAt(i);
if(!wordToChar.containsKey(word) && !charToWord.containsKey(c)){
wordToChar.put(word, c);
charToWord.put(c, word);
}else if(wordToChar.containsKey(word) && charToWord.containsKey(c)){
char d = wordToChar.get(word);
String word2 = charToWord.get(c);
if(d != c || !word.equals(word2)){
return false;
}
}else {
return false;
}
}
return true;
}
Rust
use std::collections::HashMap;
pub fn word_pattern(pattern: String, s: String) -> bool {
if pattern.len() != s.matches(' ').count() + 1 {
return false;
}
let mut p2s: HashMap<char, &str> = HashMap::new();
let mut s2p: HashMap<&str, char> = HashMap::new();
for (word, c) in s.split_ascii_whitespace().zip(pattern.chars()) {
if !p2s.contains_key(&c) && !s2p.contains_key(word) {
p2s.insert(c, word);
s2p.insert(word, c);
} else if p2s.contains_key(&c) && s2p.contains_key(word) {
let word2 = p2s.get(&c).unwrap();
let c2 = s2p.get(word).unwrap();
if word2 != &word || c2 != &c {
return false;
}
} else {
return false;
}
}
return true;
}