Rust日记:字符串哈希实现

一篇用rust实现字符串哈希的记录

字符串哈希

初版代码:

 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
use std::cmp::Ordering;
use std::io::Read;
struct StringHash {
    list: Vec<Vec<String>>,
}

impl StringHash {
    pub fn new() -> Self {
        Self {
            list: vec![Vec::<String>::new(); 1000003],
        }
    }

    pub fn insert(&mut self, input: String) -> Result<(), ()> {
        if let Some(idx) = StringHash::get_hash(&input) {
            self.list[idx].push(input);
            Ok(())
        } else {
            Err(())
        }
    }

    pub fn query(&self, input: &str) -> Option<()> {
        if let Some(idx) = StringHash::get_hash(input) {
            for item in &self.list[idx] {
                if let Ordering::Equal = input.cmp(item) {
                    return Some(());
                }
            }
        }
        None
    }

    fn get_hash(input: &str) -> Option<usize> {
        const MOD: usize = 1_000_003;
        const P: usize = 131;
        let mut hash: usize = 0;
        for item in input.bytes() {
            hash *= P;
            hash += item as usize;
            hash %= MOD;
        }
        Some(hash)
    }
}

fn main() {
    let mut input = String::new();
    std::io::stdin()
        .read_to_string(&mut input)
        .expect("Failed to read!");
    let mut iter = input.split_whitespace();
    macro_rules! next {
        ($t:ty) => {
            iter.next().unwrap().parse::<$t>().unwrap()
        };
    }
    let n = next!(usize);
    let mut cnt = 0;
    let mut string_hash = StringHash::new();
    for _ in 0..n {
        let input = next!(String).clone();
        if string_hash.query(&input).is_none() {
            string_hash.insert(input).expect("Failed to insert!");
            cnt += 1;
        }
    }

    println!("{cnt}");
}