我正在尝试编写一种算法,用于保存最近搜索的关键字。问题是用户不会触发搜索,而是每次键入内容时都会触发搜索。目前,我正在尝试保存上一个搜索到的关键字,并检查下一个关键字是否以最后一个关键字开头,以便丢弃最后一个关键字。
async _persistSearch(term) {
const serachLog = await this._getLastSearchedFile()
console.log("[SEARCH]", serachLog);
if (Object.keys(serachLog) == 0) {
serachLog.searches = [term];
serachLog.lastUpdated = Date.now()
} else if (term.startsWith(this.lastSearhed)) {
const toPersist = serachLog.searches.filter((value) => value != this.lastSearhed).push(term);
serachLog.searches = toPersist;
} else {
serachLog.searches.push(term);
}
this.lastSearhed = term;
await writeJSONFile(this.searchesFile, serachLog);
}
例如输入[so,som,some,somet,somethi,somethi,somethin,somethin,thin]成为[something]
答案 0 :(得分:0)
您应该使用Trie(前缀树)保存搜索到的关键字。假设您只处理小写英文字母,那么每个节点最多可以有26个子节点。对于每个新的搜索关键字,请调用startsWith方法以检查此新关键字是否为先前关键字的任何前缀。
如果需要有关为何在您的情况下使用Trie的更多说明,请阅读此https://en.wikipedia.org/wiki/Trie。
此数据结构的Java实现如下。
class Trie {
class TrieNode{
private char c;
private Map<Character, TrieNode> map;
private boolean isLeaf;
TrieNode() {
this.map = new HashMap<>();
}
TrieNode(char c) {
this.c = c;
this.map = new HashMap<>();
}
}
private TrieNode root;
/** Initialize your data structure here. */
public Trie() {
root = new TrieNode();
}
/** Inserts a word into the trie. */
public void insert(String word) {
TrieNode currNode = root;
for(int i = 0; i < word.length(); i++) {
char currChar = word.charAt(i);
if(!currNode.map.containsKey(currChar)) {
TrieNode newNode = new TrieNode(currChar);
currNode.map.put(currChar, newNode);
currNode = newNode;
}
else {
currNode = currNode.map.get(currChar);
}
if(i == word.length() - 1) {
currNode.isLeaf = true;
}
}
}
/** Returns if the word is in the trie. */
public boolean search(String word) {
TrieNode currNode = root;
for(int i = 0; i < word.length(); i++) {
if(!currNode.map.containsKey(word.charAt(i))) {
return false;
}
currNode = currNode.map.get(word.charAt(i));
if( i == word.length() - 1 && !currNode.isLeaf) {
return false;
}
}
return true;
}
/** Returns if there is any word in the trie that starts with the given prefix. */
public boolean startsWith(String prefix) {
TrieNode currNode = root;
for(int i = 0; i < prefix.length(); i++) {
if(!currNode.map.containsKey(prefix.charAt(i))) {
return false;
}
currNode = currNode.map.get(prefix.charAt(i));
}
return true;
}
}