Description#
Design a special dictionary that searches the words in it by a prefix and a suffix.
Implement the WordFilter
class:
WordFilter(string[] words)
Initializes the object with the words
in the dictionary.f(string pref, string suff)
Returns the index of the word in the dictionary, which has the prefix pref
and the suffix suff
. If there is more than one valid index, return the largest of them. If there is no such word in the dictionary, return -1
.
Example 1:
Input
["WordFilter", "f"]
[[["apple"]], ["a", "e"]]
Output
[null, 0]
Explanation
WordFilter wordFilter = new WordFilter(["apple"]);
wordFilter.f("a", "e"); // return 0, because the word at index 0 has prefix = "a" and suffix = "e".
Constraints:
1 <= words.length <= 104
1 <= words[i].length <= 7
1 <= pref.length, suff.length <= 7
words[i]
, pref
and suff
consist of lowercase English letters only.- At most
104
calls will be made to the function f
.
Solutions#
Solution 1#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
| class WordFilter:
def __init__(self, words: List[str]):
self.d = {}
for k, w in enumerate(words):
n = len(w)
for i in range(n + 1):
a = w[:i]
for j in range(n + 1):
b = w[j:]
self.d[(a, b)] = k
def f(self, pref: str, suff: str) -> int:
return self.d.get((pref, suff), -1)
# Your WordFilter object will be instantiated and called as such:
# obj = WordFilter(words)
# param_1 = obj.f(pref,suff)
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
| class WordFilter {
private Map<String, Integer> d = new HashMap<>();
public WordFilter(String[] words) {
for (int k = 0; k < words.length; ++k) {
String w = words[k];
int n = w.length();
for (int i = 0; i <= n; ++i) {
String a = w.substring(0, i);
for (int j = 0; j <= n; ++j) {
String b = w.substring(j);
d.put(a + "." + b, k);
}
}
}
}
public int f(String pref, String suff) {
return d.getOrDefault(pref + "." + suff, -1);
}
}
/**
* Your WordFilter object will be instantiated and called as such:
* WordFilter obj = new WordFilter(words);
* int param_1 = obj.f(pref,suff);
*/
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
| class WordFilter {
public:
unordered_map<string, int> d;
WordFilter(vector<string>& words) {
for (int k = 0; k < words.size(); ++k) {
string w = words[k];
int n = w.size();
for (int i = 0; i <= n; ++i) {
string a = w.substr(0, i);
for (int j = 0; j <= n; ++j) {
string b = w.substr(j, n - j);
d[a + "." + b] = k;
}
}
}
}
int f(string pref, string suff) {
string key = pref + "." + suff;
if (d.count(key)) return d[key];
return -1;
}
};
/**
* Your WordFilter object will be instantiated and called as such:
* WordFilter* obj = new WordFilter(words);
* int param_1 = obj->f(pref,suff);
*/
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
| type WordFilter struct {
d map[string]int
}
func Constructor(words []string) WordFilter {
d := map[string]int{}
for k, w := range words {
n := len(w)
for i := 0; i <= n; i++ {
a := w[:i]
for j := 0; j <= n; j++ {
b := w[j:]
d[a+"."+b] = k
}
}
}
return WordFilter{d}
}
func (this *WordFilter) F(pref string, suff string) int {
if v, ok := this.d[pref+"."+suff]; ok {
return v
}
return -1
}
/**
* Your WordFilter object will be instantiated and called as such:
* obj := Constructor(words);
* param_1 := obj.F(pref,suff);
*/
|
Solution 2#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
| class Trie:
def __init__(self):
self.children = [None] * 26
self.indexes = []
def insert(self, word, i):
node = self
for c in word:
idx = ord(c) - ord("a")
if node.children[idx] is None:
node.children[idx] = Trie()
node = node.children[idx]
node.indexes.append(i)
def search(self, pref):
node = self
for c in pref:
idx = ord(c) - ord("a")
if node.children[idx] is None:
return []
node = node.children[idx]
return node.indexes
class WordFilter:
def __init__(self, words: List[str]):
self.p = Trie()
self.s = Trie()
for i, w in enumerate(words):
self.p.insert(w, i)
self.s.insert(w[::-1], i)
def f(self, pref: str, suff: str) -> int:
a = self.p.search(pref)
b = self.s.search(suff[::-1])
if not a or not b:
return -1
i, j = len(a) - 1, len(b) - 1
while ~i and ~j:
if a[i] == b[j]:
return a[i]
if a[i] > b[j]:
i -= 1
else:
j -= 1
return -1
# Your WordFilter object will be instantiated and called as such:
# obj = WordFilter(words)
# param_1 = obj.f(pref,suff)
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
| class Trie {
Trie[] children = new Trie[26];
List<Integer> indexes = new ArrayList<>();
void insert(String word, int i) {
Trie node = this;
for (char c : word.toCharArray()) {
c -= 'a';
if (node.children[c] == null) {
node.children[c] = new Trie();
}
node = node.children[c];
node.indexes.add(i);
}
}
List<Integer> search(String pref) {
Trie node = this;
for (char c : pref.toCharArray()) {
c -= 'a';
if (node.children[c] == null) {
return Collections.emptyList();
}
node = node.children[c];
}
return node.indexes;
}
}
class WordFilter {
private Trie p = new Trie();
private Trie s = new Trie();
public WordFilter(String[] words) {
for (int i = 0; i < words.length; ++i) {
String w = words[i];
p.insert(w, i);
s.insert(new StringBuilder(w).reverse().toString(), i);
}
}
public int f(String pref, String suff) {
suff = new StringBuilder(suff).reverse().toString();
List<Integer> a = p.search(pref);
List<Integer> b = s.search(suff);
if (a.isEmpty() || b.isEmpty()) {
return -1;
}
int i = a.size() - 1, j = b.size() - 1;
while (i >= 0 && j >= 0) {
int c = a.get(i), d = b.get(j);
if (c == d) {
return c;
}
if (c > d) {
--i;
} else {
--j;
}
}
return -1;
}
}
/**
* Your WordFilter object will be instantiated and called as such:
* WordFilter obj = new WordFilter(words);
* int param_1 = obj.f(pref,suff);
*/
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
| type Trie struct {
children [26]*Trie
indexes []int
}
func newTrie() *Trie {
return &Trie{indexes: []int{}}
}
func (this *Trie) insert(word string, i int) {
node := this
for _, c := range word {
idx := c - 'a'
if node.children[idx] == nil {
node.children[idx] = newTrie()
}
node = node.children[idx]
node.indexes = append(node.indexes, i)
}
}
func (this *Trie) search(pref string) []int {
node := this
for _, c := range pref {
idx := c - 'a'
if node.children[idx] == nil {
return []int{}
}
node = node.children[idx]
}
return node.indexes
}
type WordFilter struct {
p *Trie
s *Trie
}
func Constructor(words []string) WordFilter {
p := newTrie()
s := newTrie()
for i, w := range words {
p.insert(w, i)
s.insert(reverse(w), i)
}
return WordFilter{p, s}
}
func (this *WordFilter) F(pref string, suff string) int {
a := this.p.search(pref)
b := this.s.search(reverse(suff))
if len(a) == 0 || len(b) == 0 {
return -1
}
i, j := len(a)-1, len(b)-1
for i >= 0 && j >= 0 {
if a[i] == b[j] {
return a[i]
}
if a[i] > b[j] {
i--
} else {
j--
}
}
return -1
}
func reverse(w string) string {
ww := []byte(w)
for i, j := 0, len(w)-1; i < j; i++ {
ww[i], ww[j] = ww[j], ww[i]
j--
}
return string(ww)
}
/**
* Your WordFilter object will be instantiated and called as such:
* obj := Constructor(words);
* param_1 := obj.F(pref,suff);
*/
|