Word Pattern II

medium backtracking string hash map

Problem

Given a pattern and a string s, return true if s matches the pattern under a bijective mapping pattern_letter ↔ substring.

Inputpattern = "abab", s = "redblueredblue"
Outputtrue
a → "red", b → "blue".

def word_pattern_match(pattern, s):
    mapping = {}
    used = set()
    def back(p, q):
        if p == len(pattern) and q == len(s):
            return True
        if p == len(pattern) or q == len(s):
            return False
        ch = pattern[p]
        if ch in mapping:
            sub = mapping[ch]
            return s.startswith(sub, q) and back(p + 1, q + len(sub))
        for k in range(q + 1, len(s) + 1):
            sub = s[q:k]
            if sub in used: continue
            mapping[ch] = sub; used.add(sub)
            if back(p + 1, k): return True
            del mapping[ch]; used.remove(sub)
        return False
    return back(0, 0)
function wordPatternMatch(pattern, s) {
  const map = new Map(), used = new Set();
  function back(p, q) {
    if (p === pattern.length && q === s.length) return true;
    if (p === pattern.length || q === s.length) return false;
    const ch = pattern[p];
    if (map.has(ch)) {
      const sub = map.get(ch);
      return s.startsWith(sub, q) && back(p + 1, q + sub.length);
    }
    for (let k = q + 1; k <= s.length; k++) {
      const sub = s.slice(q, k);
      if (used.has(sub)) continue;
      map.set(ch, sub); used.add(sub);
      if (back(p + 1, k)) return true;
      map.delete(ch); used.delete(sub);
    }
    return false;
  }
  return back(0, 0);
}
class Solution {
    Map map = new HashMap<>();
    Set used = new HashSet<>();
    public boolean wordPatternMatch(String pattern, String s) { return back(pattern, 0, s, 0); }
    boolean back(String p, int i, String s, int j) {
        if (i == p.length() && j == s.length()) return true;
        if (i == p.length() || j == s.length()) return false;
        char c = p.charAt(i);
        if (map.containsKey(c)) {
            String sub = map.get(c);
            return s.startsWith(sub, j) && back(p, i + 1, s, j + sub.length());
        }
        for (int k = j + 1; k <= s.length(); k++) {
            String sub = s.substring(j, k);
            if (used.contains(sub)) continue;
            map.put(c, sub); used.add(sub);
            if (back(p, i + 1, s, k)) return true;
            map.remove(c); used.remove(sub);
        }
        return false;
    }
}
class Solution {
    unordered_map mp;
    unordered_set used;
    bool back(const string& p, int i, const string& s, int j) {
        if (i == (int)p.size() && j == (int)s.size()) return true;
        if (i == (int)p.size() || j == (int)s.size()) return false;
        char c = p[i];
        if (mp.count(c)) {
            const string& sub = mp[c];
            return s.compare(j, sub.size(), sub) == 0 && back(p, i + 1, s, j + sub.size());
        }
        for (int k = j + 1; k <= (int)s.size(); k++) {
            string sub = s.substr(j, k - j);
            if (used.count(sub)) continue;
            mp[c] = sub; used.insert(sub);
            if (back(p, i + 1, s, k)) return true;
            mp.erase(c); used.erase(sub);
        }
        return false;
    }
public:
    bool wordPatternMatch(string pattern, string s) { return back(pattern, 0, s, 0); }
};
Time: O(n^m) Space: O(m + n)