2023-03-08 22:04:25 +08:00
|
|
|
// What is PathSet used for?
|
2023-03-06 03:07:37 +08:00
|
|
|
// For the empty_prefixes field in the EmptyPathsCache only :/
|
|
|
|
// but it could be used for more, like efficient computing of a set of paths
|
|
|
|
|
2023-03-08 22:04:25 +08:00
|
|
|
/// A set of [`Path`]
|
|
|
|
#[derive(Default, Debug, Clone)]
|
|
|
|
pub struct PathSet {
|
|
|
|
nodes: Vec<(u16, PathSet)>,
|
|
|
|
is_end: bool,
|
2023-02-21 16:46:49 +08:00
|
|
|
}
|
2023-03-08 22:04:25 +08:00
|
|
|
impl PathSet {
|
|
|
|
pub fn insert(&mut self, mut edges: impl Iterator<Item = u16>) {
|
2023-02-21 16:46:49 +08:00
|
|
|
match edges.next() {
|
|
|
|
None => {
|
2023-03-08 22:04:25 +08:00
|
|
|
self.is_end = true;
|
2023-02-21 16:46:49 +08:00
|
|
|
}
|
|
|
|
Some(first_edge) => {
|
|
|
|
for (edge, next_node) in &mut self.nodes {
|
|
|
|
if edge == &first_edge {
|
2023-03-08 22:04:25 +08:00
|
|
|
return next_node.insert(edges);
|
2023-02-21 16:46:49 +08:00
|
|
|
}
|
|
|
|
}
|
2023-03-08 22:04:25 +08:00
|
|
|
let mut rest = PathSet::default();
|
|
|
|
rest.insert(edges);
|
2023-02-21 16:46:49 +08:00
|
|
|
self.nodes.push((first_edge, rest));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2023-03-14 23:37:47 +08:00
|
|
|
pub fn remove_edge(&mut self, forbidden_edge: u16) {
|
2023-02-21 16:46:49 +08:00
|
|
|
let mut i = 0;
|
|
|
|
while i < self.nodes.len() {
|
2023-03-14 23:37:47 +08:00
|
|
|
let should_remove = if self.nodes[i].0 == forbidden_edge {
|
2023-02-21 16:46:49 +08:00
|
|
|
true
|
|
|
|
} else if !self.nodes[i].1.nodes.is_empty() {
|
|
|
|
self.nodes[i].1.remove_edge(forbidden_edge);
|
|
|
|
self.nodes[i].1.nodes.is_empty()
|
|
|
|
} else {
|
|
|
|
false
|
|
|
|
};
|
|
|
|
if should_remove {
|
|
|
|
self.nodes.remove(i);
|
|
|
|
} else {
|
|
|
|
i += 1;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2023-03-07 21:42:58 +08:00
|
|
|
pub fn final_edges_after_prefix(&self, prefix: &[u16], visit: &mut impl FnMut(u16)) {
|
2023-03-03 04:27:42 +08:00
|
|
|
let [first_edge, remaining_prefix @ ..] = prefix else {
|
2023-03-07 21:42:58 +08:00
|
|
|
for node in self.nodes.iter() {
|
2023-03-08 22:04:25 +08:00
|
|
|
if node.1.is_end {
|
2023-03-07 21:42:58 +08:00
|
|
|
visit(node.0)
|
2023-03-03 04:27:42 +08:00
|
|
|
}
|
2023-03-07 21:42:58 +08:00
|
|
|
}
|
|
|
|
return
|
2023-03-03 04:27:42 +08:00
|
|
|
};
|
|
|
|
for (edge, rest) in self.nodes.iter() {
|
|
|
|
if edge == first_edge {
|
2023-03-07 21:42:58 +08:00
|
|
|
return rest.final_edges_after_prefix(remaining_prefix, visit);
|
2023-03-03 04:27:42 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2023-03-07 21:42:58 +08:00
|
|
|
pub fn contains_prefix_of_path(&self, path: &[u16]) -> bool {
|
2023-03-08 22:04:25 +08:00
|
|
|
if self.is_end {
|
2023-02-21 20:57:34 +08:00
|
|
|
return true;
|
2023-02-21 16:46:49 +08:00
|
|
|
}
|
|
|
|
match path {
|
2023-02-21 20:57:34 +08:00
|
|
|
[] => false,
|
2023-02-21 16:46:49 +08:00
|
|
|
[first_edge, remaining_path @ ..] => {
|
2023-02-21 20:57:34 +08:00
|
|
|
for (edge, rest) in self.nodes.iter() {
|
2023-02-21 16:46:49 +08:00
|
|
|
if edge == first_edge {
|
|
|
|
return rest.contains_prefix_of_path(remaining_path);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
false
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|