Welcome to Subscribe On Youtube
291. Word Pattern II
Description
Given a pattern and a string s, return true if s matches the pattern.
A string s matches a pattern if there is some bijective mapping of single characters to non-empty strings such that if each character in pattern is replaced by the string it maps to, then the resulting string is s. A bijective mapping means that no two characters map to the same string, and no character maps to two different strings.
Example 1:
Input: pattern = "abab", s = "redblueredblue" Output: true Explanation: One possible mapping is as follows: 'a' -> "red" 'b' -> "blue"
Example 2:
Input: pattern = "aaaa", s = "asdasdasdasd" Output: true Explanation: One possible mapping is as follows: 'a' -> "asd"
Example 3:
Input: pattern = "aabb", s = "xyzabcxzyabc" Output: false
Constraints:
1 <= pattern.length, s.length <= 20patternandsconsist of only lowercase English letters.
Solutions
This solution code defines a solution to a pattern matching problem, where the goal is to determine if a given string s can be segmented in a way that matches a given pattern pattern. Each character in pattern represents a distinct part of s, and the same character in pattern should map to the same segment in s.
The solution employs Depth-First Search (DFS) to explore all possible ways of segmenting s to match the pattern. Here’s a detailed breakdown of how the code works:
Function: wordPatternMatch
- Parameters: It takes a
pattern(a string where each character represents a pattern to match) ands(the string to be matched against the pattern).
Helper Function: dfs
-
Purpose: The
dfsfunction is a recursive helper function that attempts to match thepatternwith segments ofs. It uses two additional lists,pathpandpaths, to keep track of the current segment mappings frompatterntos. -
Base Case: The recursion ends successfully (
return True) if bothp(remaining pattern) ands(remaining string) are empty, meaning a complete match has been found. It returnsFalseifpis empty butsis not, or if the remaining pattern length is greater than the remaining string length, indicating a mismatch. -
Recursion and Backtracking:
- The function iterates through
s, trying to match the current character inpattern(p[0]) with every possible leading segment ofs. - At each iteration, it adds the current pattern character to
pathpand the current segment being considered (s[:i + 1]) topaths. - It checks for a valid mapping: if the lengths of
pathpandpathsare equal, and the number of unique elements inpaths,pathp, and their zipped combination (pairs of pattern and corresponding segment) are the same. This condition ensures that each character in the pattern maps to a unique and consistent segment ins.- If the condition is met, it recursively calls
dfswith the next character in the pattern and the remaining string, excluding the current segment. - If the recursive call returns
True, indicating a successful match for the remaining pattern and string, the current call also returnsTrue.
- If the condition is met, it recursively calls
- Implements backtracking by removing the last added elements from
pathpandpathsbefore moving to the next iteration. - Returns
Falseif no valid mapping is found for any segment ofsagainst the current character inpattern.
- The function iterates through
Return Value
- The initial call to
dfsstarts with the fullpatternands, along with empty lists forpathpandpaths. The return value of this call determines whether a valid pattern match exists for the entire strings.
-
class Solution { private Set<String> vis; private Map<Character, String> d; private String p; private String s; private int m; private int n; public boolean wordPatternMatch(String pattern, String s) { vis = new HashSet<>(); d = new HashMap<>(); this.p = pattern; this.s = s; m = p.length(); n = s.length(); return dfs(0, 0); } private boolean dfs(int i, int j) { if (i == m && j == n) { return true; } if (i == m || j == n || m - i > n - j) { return false; } char c = p.charAt(i); for (int k = j + 1; k <= n; ++k) { String t = s.substring(j, k); if (d.getOrDefault(c, "").equals(t)) { if (dfs(i + 1, k)) { return true; } } if (!d.containsKey(c) && !vis.contains(t)) { d.put(c, t); vis.add(t); if (dfs(i + 1, k)) { return true; } vis.remove(t); d.remove(c); } } return false; } } -
class Solution { public: bool wordPatternMatch(string pattern, string s) { unordered_set<string> vis; unordered_map<char, string> d; return dfs(0, 0, pattern, s, vis, d); } bool dfs(int i, int j, string& p, string& s, unordered_set<string>& vis, unordered_map<char, string>& d) { int m = p.size(), n = s.size(); if (i == m && j == n) return true; if (i == m || j == n || m - i > n - j) return false; char c = p[i]; for (int k = j + 1; k <= n; ++k) { string t = s.substr(j, k - j); if (d.count(c) && d[c] == t) { if (dfs(i + 1, k, p, s, vis, d)) return true; } if (!d.count(c) && !vis.count(t)) { d[c] = t; vis.insert(t); if (dfs(i + 1, k, p, s, vis, d)) return true; vis.erase(t); d.erase(c); } } return false; } }; -
class Solution(object): def wordPatternMatch(self, pattern, s): """ :type pattern: str :type s: str :rtype: bool """ # pathp: path for pattern # paths: path for matched strings def dfs(p, s, pathp, paths): if len(p) == len(s) == 0: return True if len(p) == 0 or len(p) > len(s): return False for i in range(0, len(s)): pathp.append(p[0]) paths.append(s[:i + 1]) # same as in Word-Pattern-I, for checking if valid if len(pathp) == len(paths) and len(set(paths)) == len(set(pathp)) == len(set(zip(paths, pathp))): if dfs(p[1:], s[i + 1:], pathp, paths): return True pathp.pop() paths.pop() return False return dfs(pattern, s, [], []) ############ ''' >>> d = {} >>> d.get('a') >>> >>> r = d.get('a') >>> r >>> >>> if not r: ... print('aa') aa ''' class Solution: def wordPatternMatch(self, pattern: str, s: str) -> bool: def dfs(i, j): if i == m and j == n: return True if i == m or j == n or n - j < m - i: return False for k in range(j, n): t = s[j: k + 1] if pattern[i] in d and d[pattern[i]] == t: if dfs(i + 1, k + 1): return True elif pattern[i] not in d and t not in vis: d[pattern[i]] = t vis.add(t) if dfs(i + 1, k + 1): return True d.pop(pattern[i]) vis.remove(t) return False m, n = len(pattern), len(s) d = {} vis = set() return dfs(0, 0) -
func wordPatternMatch(pattern string, s string) bool { m, n := len(pattern), len(s) vis := map[string]bool{} d := map[byte]string{} var dfs func(i, j int) bool dfs = func(i, j int) bool { if i == m && j == n { return true } if i == m || j == n || m-i > n-j { return false } c := pattern[i] for k := j + 1; k <= n; k++ { t := s[j:k] if v, ok := d[c]; ok && v == t { if dfs(i+1, k) { return true } } if _, ok := d[c]; !ok && !vis[t] { d[c] = t vis[t] = true if dfs(i+1, k) { return true } delete(d, c) vis[t] = false } } return false } return dfs(0, 0) }