我正在Rust中编写一个Trie数据结构,以实现Aho-Corasick算法。 TrieNode
结构代表一个节点,如下所示:
use std::collections::{HashMap, HashSet, VecDeque};
struct TrieNode {
next_ids: HashMap<char, usize>,
kw_indices: HashSet<usize>,
fail_id: Option<usize>,
}
我使用与世代竞技场相同的策略来实现Trie,将所有节点存储在一个Vec
中,并使用它们的索引相互引用。在创建所有节点之后构建自动机时,我试图在不使用clone()
方法的情况下使以下代码工作:
fn build_ac_automaton(nodes: &mut Vec<TrieNode>) {
let mut q = VecDeque::new();
for &i in nodes[0].next_ids.values() {
q.push_back(i);
nodes[i].fail_id = Some(0);
}
// ...
}
但是借阅检查员对此并不满意:
error[E0502]: cannot borrow `*nodes` as mutable because it is also borrowed as immutable
|
| for &i in nodes[0].next_ids.values() {
| ----- - immutable borrow ends here
| |
| immutable borrow occurs here
| q.push_back(i);
| nodes[i].fail_id = Some(0);
| ^^^^^ mutable borrow occurs here
在不使用昂贵的clone()
方法的情况下实现上述目标的另一种方法(如果有)?
答案 0 :(得分:5)
分割切片:
fn build_ac_automaton(nodes: &mut Vec<TrieNode>) {
let mut q = VecDeque::new();
let (first, rest) = nodes.split_first_mut();
for &i in first.next_ids.values() {
q.push_back(i);
if i == 0 {
first.fail_id = Some(0);
} else {
rest[i-1].fail_id = Some(0);
}
}
...
}
但是,仅克隆next_ids
可能会降低成本:
fn build_ac_automaton(nodes: &mut Vec<TrieNode>) {
let mut q = VecDeque::new();
let ids: Vec<_> = nodes[0].next_ids.values().cloned().collect();
for &i in ids {
q.push_back(i);
nodes[i].fail_id = Some(0);
}
...
}