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
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
#![warn(clippy::all)]
#![warn(clippy::pedantic)]
#![warn(clippy::nursery)]
#![warn(clippy::cargo)]
#![deny(missing_docs)]
use std::collections::BTreeMap;
#[derive(Default)]
pub struct AutoComplete<T: PartialOrd + Ord + Clone + Default> {
trie: Node<T>,
}
impl<T> AutoComplete<T>
where
T: PartialOrd + Ord + Clone + Default,
{
pub fn new(dict: &[(String, T)]) -> Self {
let mut trie = Self::default();
dict.iter().for_each(|v| trie.insert(&(&v.0, v.1.clone())));
trie
}
pub fn insert(&mut self, value: &(&str, T)) {
let mut curr = &mut self.trie;
for (c, v) in value.0.char_indices() {
curr = curr
.children
.entry(v)
.and_modify(|f| {
if c == (value.0.len() - 1) {
f.weight = value.1.clone();
f.is_word = true;
}
})
.or_insert_with(|| Node::new(value.0[0..=c].to_string(), c == (value.0.len() - 1), value.1.clone()));
}
}
pub fn change_weight(&mut self, value: &(&str, T)) -> Result<(), String> {
let mut curr = &mut self.trie;
for v in value.0.chars() {
curr = match curr.children.get_mut(&v) {
Some(a) => a,
None => return Err(format!("Failed to set the weight for {}!", value.0)),
};
}
curr.weight = value.1.clone();
Ok(())
}
pub fn get_strings_for_prefix(&self, prefix: &str) -> Option<Vec<String>> {
let mut results: Vec<(String, T)> = Vec::new();
let mut curr = &self.trie;
for v in prefix.chars() {
curr = match curr.children.get(&v) {
Some(a) => a,
None => return None,
}
}
Self::find_all_child_words(curr, &mut results);
results.sort_by(|(_, a), (_, b)| b.cmp(a));
Some(results.into_iter().map(|(v, _)| v).collect())
}
fn find_all_child_words(node: &Node<T>, results: &mut Vec<(String, T)>) {
if node.is_word {
results.push((node.prefix.clone(), node.weight.clone()));
}
node.children.keys().for_each(|v| Self::find_all_child_words(node.children.get(v).unwrap(), results));
}
}
#[derive(Default)]
struct Node<T>
where
T: PartialOrd + Ord + Default + Clone,
{
prefix: String,
children: BTreeMap<char, Node<T>>,
is_word: bool,
weight: T,
}
impl<T> Node<T>
where
T: PartialOrd + Ord + Default + Clone,
{
fn new(prefix: String, is_word: bool, weight: T) -> Self {
Self {
prefix,
children: BTreeMap::new(),
is_word,
weight: if is_word { weight } else { T::default() },
}
}
}