You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

135 lines
3.2 KiB

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

package class51;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.TreeSet;
public class Problem_0642_DesignSearchAutocompleteSystem {
class AutocompleteSystem {
public class TrieNode {
public TrieNode father;
public String path;
public TrieNode[] nexts;
public TrieNode(TrieNode f, String p) {
father = f;
path = p;
nexts = new TrieNode[27];
}
}
public class WordCount implements Comparable<WordCount> {
public String word;
public int count;
public WordCount(String w, int c) {
word = w;
count = c;
}
public int compareTo(WordCount o) {
return count != o.count ? (o.count - count) : word.compareTo(o.word);
}
}
// 题目的要求只输出排名前3的列表
public final int top = 3;
public final TrieNode root = new TrieNode(null, "");
// 某个前缀树节点,上面的有序表,不在这个节点内部
// 外挂
public HashMap<TrieNode, TreeSet<WordCount>> nodeRankMap = new HashMap<>();
// 字符串 "abc" 7次 -> ("abc", 7)
public HashMap<String, WordCount> wordCountMap = new HashMap<>();
public String path;
public TrieNode cur;
// ' ' -> 0
// 'a' -> 1
// 'b' -> 2
// ...
// 'z' -> 26
// '`' a b .. z
private int f(char c) {
return c == ' ' ? 0 : (c - '`');
}
public AutocompleteSystem(String[] sentences, int[] times) {
path = "";
cur = root;
for (int i = 0; i < sentences.length; i++) {
String word = sentences[i];
int count = times[i];
WordCount wc = new WordCount(word, count - 1);
wordCountMap.put(word, wc);
for (char c : word.toCharArray()) {
input(c);
}
input('#');
}
}
// 之前已经有一些历史了!
// 当前键入 c 字符
// 请顺着之前的历史根据c字符是什么继续
// path : 之前键入的字符串整体
// cur : 当前滑到了前缀树的哪个节点
public List<String> input(char c) {
List<String> ans = new ArrayList<>();
if (c != '#') {
path += c;
int i = f(c);
if (cur.nexts[i] == null) {
cur.nexts[i] = new TrieNode(cur, path);
}
cur = cur.nexts[i];
if (!nodeRankMap.containsKey(cur)) {
nodeRankMap.put(cur, new TreeSet<>());
}
int k = 0;
// for循环本身就是根据排序后的顺序来遍历
for (WordCount wc : nodeRankMap.get(cur)) {
if (k == top) {
break;
}
ans.add(wc.word);
k++;
}
}
// c = # path = "abcde"
// #
// #
// #
// a b .. #
if (c == '#' && !path.equals("")) {
// 真的有一个有效字符串需要加入path
if (!wordCountMap.containsKey(path)) {
wordCountMap.put(path, new WordCount(path, 0));
}
// 有序表内部的小对象,该小对象参与排序的指标数据改变
// 但是有序表并不会自动刷新
// 所以,删掉老的,加新的!
WordCount oldOne = wordCountMap.get(path);
WordCount newOne = new WordCount(path, oldOne.count + 1);
while (cur != root) {
nodeRankMap.get(cur).remove(oldOne);
nodeRankMap.get(cur).add(newOne);
cur = cur.father;
}
wordCountMap.put(path, newOne);
path = "";
// cur 回到头了
}
return ans;
}
}
}