use std::cell::RefCell;
use std::cmp::Eq;
use std::cmp::PartialEq;
use std::collections::HashMap;
use std::hash::Hash;
use std::rc::Rc;
#[derive(Debug, Clone)]
pub enum Leaf<T> {
End(T),
Nil,
}
impl<T: PartialEq> PartialEq for Leaf<T> {
fn eq(&self, other: &Self) -> bool {
match self {
Leaf::End(d) => match other {
Leaf::End(od) => d == od,
Leaf::Nil => false,
},
Leaf::Nil => match other {
Leaf::End(_) => false,
Leaf::Nil => true,
},
}
}
}
#[derive(Debug)]
pub struct Node<T: Eq + Hash + Clone> {
pub node: HashMap<T, Rc<RefCell<Node<T>>>>,
pub leaf: Leaf<T>,
}
pub trait Trie<T: Eq + Hash + Clone> {
fn insert_seq(node: Rc<RefCell<Node<T>>>, words: &[T], leaf: Leaf<T>) {
let (index, mut m_node) = Node::find_last_node(node.clone(), &words);
for word in &words[index..] {
m_node = Node::add_node(m_node.clone(), word.to_owned());
}
Node::add_leaf(m_node, leaf);
}
fn get_leaf(node: Rc<RefCell<Node<T>>>, words: &[T]) -> Leaf<T> {
let length = words.len();
let (index, node) = Node::find_last_node(node.clone(), words);
if index + 1 == length {
let m_node = node.borrow();
m_node.leaf.to_owned()
} else {
Leaf::Nil
}
}
fn find_node(node: Rc<RefCell<Node<T>>>, word: &T) -> (bool, Rc<RefCell<Node<T>>>) {
let m_node = node.borrow();
match m_node.node.get(word) {
Some(mm_node) => (true, mm_node.clone()),
None => (false, node.clone()),
}
}
fn find_last_node(node: Rc<RefCell<Node<T>>>, words: &[T]) -> (usize, Rc<RefCell<Node<T>>>) {
let mut m_node = node.clone();
let mut out_index = 0;
for (index, word) in words.iter().enumerate() {
let (label, mm_node) = Node::find_node(m_node.clone(), word);
if label {
out_index = index + 1;
m_node = mm_node;
}
}
(out_index, m_node.clone())
}
fn add_leaf(node: Rc<RefCell<Node<T>>>, leaf: Leaf<T>) -> bool {
let mut m_node = node.borrow_mut();
m_node.leaf = leaf;
true
}
fn add_node(node: Rc<RefCell<Node<T>>>, node_data: T) -> Rc<RefCell<Node<T>>> {
let mut m_node = node.borrow_mut();
let new_node = Node::new();
m_node.node.insert(node_data, new_node.clone());
new_node.clone()
}
}
impl<T: Eq + Hash + Clone> Trie<T> for Node<T> {}
impl<T: Eq + Hash + Clone> Node<T> {
pub fn new() -> Rc<RefCell<Node<T>>> {
Rc::new(RefCell::new(Node {
node: HashMap::new(),
leaf: Leaf::Nil,
}))
}
}
#[test]
fn name() {
let node = Node::new();
let seq = vec!["你".to_string(), "我".to_string(), "他".to_string()];
let seq1 = vec!["你".to_string(), "我".to_string()];
Node::insert_seq(node.clone(), &seq, Leaf::End("intention".to_string()));
let leaf = Node::get_leaf(node.clone(), &seq1);
assert_ne!(leaf, Leaf::End("intention".to_string()));
}