291. Word Pattern II

38 阅读1分钟

image.png

Solution

  • Use a map to track pattern character -> substring.
  • the mapping is bi-direction, so we need to check. Use a set to ensure no substring is reused for a different pattern character.
  • At each recursion level:
    • If the character is already mapped, check if the next part of the string matches.
    • If it's not mapped yet, try every possible substring starting at the current index as a candidate.
class Solution {
    public boolean wordPatternMatch(String pattern, String s) {
        Map<Character, String> map = new HashMap<>();
        Set<String> strMatched = new HashSet<>();
        return backtrack(pattern, 0, s, 0, map, strMatched);
    }

    public boolean backtrack(String pattern, int pIdx, String s, int sIdx, 
                                Map<Character, String> map, Set<String> strMatched) {
        
        //  if we reached the end of the pattern
        if (pIdx == pattern.length()) {
            return sIdx == s.length();
        }

        char c = pattern.charAt(pIdx);

        // If the character is already mapped, 
        // check if the next part of the string matches
        if (map.containsKey(c)) {
            String str = map.get(c);

            if (!s.startsWith(str, sIdx)) {
                return false;
            }

            return backtrack(pattern, pIdx + 1, s, sIdx + str.length(), map, strMatched);
        }

        // try to match pattern[pIdx] to every s.substring starting at sIdx
        // For abab redblueredblue: a-r a-re a-red a-redb
        for (int i = sIdx; i < s.length(); i++) {
            String newSubstr = s.substring(sIdx, i + 1);

            // Skip if this word is already mapped to another character
            // For example ab zz, a->z already exist when dfs to b
            if (strMatched.contains(newSubstr)) {
                continue;
            }

            map.put(c, newSubstr);
            strMatched.add(newSubstr);

            if (backtrack(pattern, pIdx + 1, s, i + 1, map, strMatched)) {
                return true;
            }

            strMatched.remove(newSubstr);
            map.remove(c);
        }

        return false;
    }
}