【问题标题】:What's the fastest way to check if a string is in a static compile-time set?检查字符串是否在静态编译时集中的最快方法是什么?
【发布时间】:2018-11-10 00:56:54
【问题描述】:

我知道哈希码通常是检查动态集的最快方法,但我想知道检查动态字符串是否在编译时已知的只读字符串集中的最快方法是什么。 (我的意思主要是 {length: usize; chars: &[u8]} 字符串,而不是绳索或 cons 字符串。)

目前,我通常在做这样的事情,但似乎不是最理想的:

// What I mean
let keywords = Set::new(["do", "if", "in", "for", "new", "try"]);
fun is_keyword(s: &str) { keywords.contains(s) }

// What I write
function is_keyword(s: &str) {
    match s.length() {
        2 -> s == "do" || s == "if" || s == "in",
        3 -> s == "for" || s == "new" || s == "try",
        // etc.
        _ -> false
    }
}

对于 C 风格的字符串集,有什么比从第二个变体派生的更快的方法吗?或者它是否尽可能快?

这与语言无关 - 我不在乎答案使用什么语言。由于熟悉,我只是使用 Rust。

【问题讨论】:

  • 最快的是生成trie的编译时间,这给了O(L)时间,其中L是您要查找的字符串的长度。

标签: string algorithm language-agnostic


【解决方案1】:

对于静态集,您可以使用完美散列。这本质上是一个哈希表,但是哈希函数保证集合中的每个字符串都哈希到表中的唯一索引。

要测试动态字符串,您只需使用完美哈希函数将其哈希到索引中,然后查看该索引处的唯一字符串是否与测试字符串匹配。

谷歌搜索会找到很多不同的方法来进行完美的散列。这里描述了我的最爱之一:http://cmph.sourceforge.net/papers/chm92.pdf

它通常用于编译器中的关键字匹配,或在支持该功能的语言中实现字符串的 switch/case。

【讨论】:

    【解决方案2】:

    就像你说的,似乎最快的方法是散列字符串。您当前的方式将花费 O(N) 时间来搜索集合中最大的字符串,或者根本不在集合中的字符串。

    【讨论】:

      猜你喜欢
      • 2013-07-06
      • 1970-01-01
      • 2021-12-28
      • 1970-01-01
      • 1970-01-01
      • 2018-12-31
      • 1970-01-01
      • 2011-08-27
      • 2013-08-12
      相关资源
      最近更新 更多