LeetCode Solutions
291. Word Pattern II
Time: $O(|\texttt{pattern}|^{|\texttt{s}|})$ Space: $O(|\texttt{pattern}|^{|\texttt{s}|})$
class Solution {
public:
bool wordPatternMatch(string pattern, string s) {
return isMatch(pattern, 0, s, 0, unordered_map<char, string>(),
unordered_set<string>());
}
private:
bool isMatch(const string& pattern, int i, const string& s, int j,
unordered_map<char, string>&& charToString,
unordered_set<string>&& seen) {
if (i == pattern.length() && j == s.length())
return true;
if (i == pattern.length() || j == s.length())
return false;
const char c = pattern[i];
if (charToString.count(c)) {
const string& t = charToString[c];
// Check if we can match t w/ s[j:]
if (s.substr(j).find(t) == string::npos)
return false;
// If can match, so continue match the rest
return isMatch(pattern, i + 1, s, j + t.length(), move(charToString),
move(seen));
}
for (int k = j; k < s.length(); ++k) {
const string& t = s.substr(j, k - j + 1);
// This string is already mapped by other character
if (seen.count(t))
continue;
charToString[c] = t;
seen.insert(t);
if (isMatch(pattern, i + 1, s, k + 1, move(charToString), move(seen)))
return true;
// Backtracking
charToString.erase(c);
seen.erase(t);
}
return false;
}
};
class Solution {
public boolean wordPatternMatch(String pattern, String s) {
return isMatch(pattern, 0, s, 0, new HashMap<>(), new HashSet<>());
}
private boolean isMatch(final String pattern, int i, final String s, int j,
Map<Character, String> charToString, Set<String> seen) {
if (i == pattern.length() && j == s.length())
return true;
if (i == pattern.length() || j == s.length())
return false;
final char c = pattern.charAt(i);
if (charToString.containsKey(c)) {
final String t = charToString.get(c);
// Check if we can match t w/ s[j:]
if (!s.startsWith(t, j))
return false;
// If can match, so continue match the rest
return isMatch(pattern, i + 1, s, j + t.length(), charToString, seen);
}
for (int k = j; k < s.length(); ++k) {
final String t = s.substring(j, k + 1);
// This string is already mapped by other character
if (seen.contains(t))
continue;
charToString.put(c, t);
seen.add(t);
if (isMatch(pattern, i + 1, s, k + 1, charToString, seen))
return true;
// Backtracking
charToString.remove(c);
seen.remove(t);
}
return false;
}
}
class Solution:
def wordPatternMatch(self, pattern: str, s: str) -> bool:
def isMatch(i: int, j: int, charToString: Dict[chr, str], seen: Set[str]) -> bool:
if i == len(pattern) and j == len(s):
return True
if i == len(pattern) or j == len(s):
return False
c = pattern[i]
if c in charToString:
t = charToString[c]
# Check if we can match t w// s[j..j + len(t))
if t not in s[j:]:
return False
# If can match, so continue match the rest
return isMatch(i + 1, j + len(t), charToString, seen)
for k in range(j, len(s)):
t = s[j:k + 1]
# This is already mapped by other character
if t in seen:
continue
charToString[c] = t
seen.add(t)
if isMatch(i + 1, k + 1, charToString, seen):
return True
# Backtracking
del charToString[c]
seen.remove(t)
return False
return isMatch(0, 0, {}, set())