【问题标题】:Algorithm for shortest prefix matching?最短前缀匹配算法?
【发布时间】:2012-02-18 04:48:24
【问题描述】:

给定字符串 p 和字符串列表,找到以 p 为前缀的最短字符串。

我知道蛮力方法,但最佳方法是什么?

例如

p = "foo bar"
list = {"foo bar 1",
        "foo bar foo bar",
        "bar foo foo foo bar bar"};

应该返回“foo bar 1”

【问题讨论】:

  • 请解释为什么它不会返回"foo bar 1"
  • 如果list 包含"foo b" 怎么办?

标签: algorithm


【解决方案1】:

如果您已经有一个搜索空间(在您的情况下,是一个相对恒定的list),那么生成一个 trie 或其他一些合适的结构将有助于搜索很多。从 Wikipedia 开始,它对这一点进行了足够详细的解释以帮助您入门:

这是上面文章中使用单词的图片(很容易扩展到使用任何类型的字符串甚至非字符串):

本文提供了与其他合适结构的一些性能比较,这对您的情况很有帮助。

请注意,如果列表变化足够大,那么这种方法的回报可能会降低,或者与蛮力相比,您的性能甚至可能更差。

【讨论】:

    【解决方案2】:

    您可能已经想到的简单方法基本上只是在每次传递后检查字符串的长度。

    使用伪 C#:

    int length = 0, index;
    string p = "foo bar"
    string[] list = new string[]{"foo bar 1",
        "foo bar foo bar",
        "bar foo foo foo bar bar"};
    for(int i = 0; i < list.Length; i++) {
        if(list[i].Contains(p)) {
            if(list[i].Length < length) {
                index = i;
                length = list[i].Length;
            }
        }
    }
    MessageBox.Show("The shortest one is " + list[index]);
    

    【讨论】:

      【解决方案3】:

      如果您需要单个 p 运行它,那么直接的方法:

      1. 查找lst 中所有以p 开头的字符串
      2. 找出其中最短的

      它已经是最优的,它在时间上是O(n),在空间上是O(1),在Python中:

      shortest_with_prefix = min((s for s in lst if s.startswith(p)), key=len)
      

      如果有多个p,但lst 相同,那么您可以将lst 预处理成前缀树(Trie) 以加快多个搜索速度,在Python 中:

      from pytrie import StringTrie # pip install pytrie
      
      trie = StringTrie.fromkeys(lst)
      shortest_with_prefix = min(trie.iterkeys(prefix=p), key=len)
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2014-05-02
        • 2019-01-11
        • 2013-06-03
        • 2018-04-21
        • 2011-07-23
        • 1970-01-01
        • 1970-01-01
        • 2013-03-06
        相关资源
        最近更新 更多