745. Prefix and Suffix Search

Given many words, words[i] has weight i.

Design a class WordFilter that supports one function, WordFilter.f(String prefix, String suffix). It will
return the word with given prefix and suffix with maximum weight. If no word exists, return -1.

Examples:

Input:
WordFilter(["apple"])
WordFilter.f("a", "e") // returns 0
WordFilter.f("b", "") // returns -1

Note:

    words has length in range [1, 15000].
    For each test case, up to words.length queries WordFilter.f may be made.
    words[i] has length in range [1, 10].
    prefix, suffix have lengths in range [0, 10].
    words[i] and prefix, suffix queries consist of lowercase letters only.
  • Preprocess word to suffix + { + word

The trick: { ascill code –> ‘z’ + 1 [ —> ‘Z’ + 1 becoming the 27th node of the tier

O(NK^2 + QK)


class WordFilter {
    Node root;
    public WordFilter(String[] words) {
        root = new Node();
        root.index = words.length-1;
        for(int i = 0; i < words.length; i++) {
            for(int j = words[i].length(); j >= 0; j--) {
                String s = words[i].substring(j);
                String w =  s + "{" + words[i];
                Node curr = root;
                for(int k = 0; k < w.length(); k++) {
                    char c = w.charAt(k);
                    if(curr.arr[c-'a'] == null) curr.arr[c-'a'] = new Node();
                    curr = curr.arr[c-'a'];
                    curr.index = i;
                }
            }
        }
    }

    public int f(String prefix, String suffix) {
        String w = suffix + "{" + prefix;
        Node n = root;
        for(int i = 0; i < w.length(); i++) {
            char c = w.charAt(i);
            if(n.arr[c-'a'] == null) return -1;
            n = n.arr[c-'a'];
        }
        return n.index;
    }


    class Node {
        Node[] arr = new Node[27];
        int index = -1;
    }
}
  • Two Tier

Intersection of two sets, pick the largest index

O(KN + Q(K+N))

class WordFilter {
    Node pre, suf;
    public WordFilter(String[] words) {
        // System.out.println(Arrays.toString(words));
        pre = new Node();
        suf = new Node();
        HashSet<Integer> all = new HashSet<>();
        for(int i = 0; i < words.length; i++) all.add(i);
        pre.set = all;
        suf.set = all;
        for(int i = 0; i < words.length; i++) {
            String w = words[i];
            Node pc = pre, sc = suf;
            for(int j = 0; j < w.length(); j++) {
                char c = w.charAt(j);
                if(pc.arr[c-'a'] == null) pc.arr[c-'a'] = new Node();
                pc = pc.arr[c-'a'];
                pc.set.add(i);
            }
            for(int j = w.length()-1; j >= 0; j--) {
                char c = w.charAt(j);
                if(sc.arr[c-'a'] == null) sc.arr[c-'a'] = new Node();
                sc = sc.arr[c-'a'];
                sc.set.add(i);
            }

        }
    }

    public int f(String prefix, String suffix) {
        Node pc = pre, sc = suf;
        for(int i = 0; i < prefix.length(); i++) {
            char c = prefix.charAt(i);
            if(pc.arr[c-'a'] == null) return -1;
            pc = pc.arr[c-'a'];
        }
        for(int i = suffix.length()-1; i >= 0; i--) {
            char c = suffix.charAt(i);
            if(sc.arr[c-'a'] == null) return -1;
            sc = sc.arr[c-'a'];
        }

        int result = -1;
        for(int i : pc.set) {
            if(sc.set.contains(i)) {
                result = Math.max(result, i);
            }
        }
        return result;
    }

    class Node {
        Node[] arr = new Node[26];
        HashSet<Integer> set = new HashSet<>();
    }
}