设计一个包含一些单词的特殊词典,并能够通过前缀和后缀来检索单词。
实现 WordFilter
类:
WordFilter(string[] words)
使用词典中的单词words
初始化对象。f(string pref, string suff)
返回词典中具有前缀prefix
和后缀suff
的单词的下标。如果存在不止一个满足要求的下标,返回其中 最大的下标 。如果不存在这样的单词,返回-1
。
示例:
输入
["WordFilter", "f"]
[[["apple"]], ["a", "e"]]
输出
[null, 0]
解释
WordFilter wordFilter = new WordFilter(["apple"]);
wordFilter.f("a", "e"); // 返回 0 ,因为下标为 0 的单词:前缀 prefix = "a" 且 后缀 suff = "e" 。
提示:
1 <= words.length <= 104
1 <= words[i].length <= 7
1 <= pref.length, suff.length <= 7
words[i]
、pref
和suff
仅由小写英文字母组成- 最多对函数
f
执行104
次调用
class WordFilter {
/**
* 通过构建前缀字典树与后缀字典树
* 提高查询效率
*/
class Tire {
Tire[] child;
// 存储能够到达这个节点的下标
List<Integer> indexes;
public Tire() {
child = new Tire[26];
indexes = new ArrayList<>();
}
}
/**
* 前缀字典树
*/
private Tire preRoot;
/**
* 后缀字典树
*/
private Tire sufRoot;
/**
* 构建字典树
* @param index 单词下表
* @param word 单词
* @param root 字典树根节点
*/
private void buildTrie(int index, String word, Tire root) {
Tire cur = root;
for (char ch : word.toCharArray()) {
int i = ch - 'a';
if (cur.child[i] == null) {
cur.child[i] = new Tire();
}
cur = cur.child[i];
cur.indexes.add(index);
}
}
/**
* 获取下标列表
* @param word 前缀或后缀
* @param root 字典树根节点
* @return 下标列表, 当不存在相应前缀或后缀时返回null
*/
private List<Integer> getIndexes(String word, Tire root) {
Tire cur = root;
for (char ch : word.toCharArray()) {
int i = ch - 'a';
if (cur.child[i] == null) {
return null;
}
cur = cur.child[i];
}
return cur.indexes;
}
public WordFilter(String[] words) {
preRoot = new Tire();
sufRoot = new Tire();
// 构建前缀字典树, 后缀字典树
for (int i = 0; i < words.length; i++) {
buildTrie(i, words[i], preRoot);
buildTrie(i, new StringBuilder(words[i]).reverse().toString(), sufRoot);
}
}
public int f(String pref, String suf) {
// 获取前缀下表列表
List<Integer> preList = getIndexes(pref, preRoot);
// 获取后缀下表列表
List<Integer> sufList = getIndexes(new StringBuilder(suf).reverse().toString(), sufRoot);
if (preList == null || sufList == null) {
return -1;
}
// 比较找最大下标
for (int i = preList.size() - 1, j = sufList.size() - 1; i >= 0 && j >= 0 ;) {
if (preList.get(i) > sufList.get(j)) {
i--;
} else if (preList.get(i) < sufList.get(j)) {
j--;
} else {
return preList.get(i);
}
}
return -1;
}
public static void main(String[] args) {
WordFilter filter = new WordFilter(new String[]{"abbba","abba"});
int index = filter.f("ab", "ba");
System.out.println(index);
}
}