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

2 years ago
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;
}
}
}