字符串算法问题 - 单词起点

时间:2010-08-07 20:27:07

标签: algorithm string

我有一个问题,而且我不太确定如何解决它而不会走低效率的路线。说我有一个单词列表:

  • 苹果
  • 电弧
  • Abraid
  • Braide
  • 布雷
  • 布尔

我想要做的是处理这个列表并获得每个单词以一定深度开头的内容,例如

  • a - Apple,Ape,Arc,Abraid
  • ab - Abraid
  • ar -Arc
  • ap - Apple,Ape
  • b - Bridge,Braide,Bray,Boolean
  • br - Bridge,Braide,Bray
  • bo - 布尔

有什么想法吗?

5 个答案:

答案 0 :(得分:11)

您可以使用Trie结构。

       (root)
         / 
        a - b - r - a - i - d
       / \   \
      p   r   e
     / \   \
    p   e   c
   /
  l
 /
e

只需找到您想要的节点并获取其所有后代,例如,如果我需要ap-

       (root)
         / 
        a - b - r - a - i - d
       / \   \
     [p]  r   e
     / \   \
    p   e   c
   /
  l
 /
e

答案 1 :(得分:2)

我不知道你在想什么,当你说“效率低下的路线”时,会想到很明显的解决方案(可能是你想到的那个)。 Trie看起来像是这类问题的结构,但它在内存方面成本很高(存在很多重复),我不确定它会让你的情况变得更快。也许内存使用会得到回报,如果要多次检索信息,但是你的答案显示,你想生成一次输出文件并存储它。所以在你的情况下,Trie将被生成只是为了遍历一次。我认为这没有道理。

我的建议是只按词汇顺序对单词列表进行排序,然后按顺序遍历列表的次数与开头的最大长度相同。

create a dictionary with keys being strings and values being lists of strings

for(i = 1 to maxBeginnigLength)
{
    for(every word in your sorted list)
    {
        if(the word's length is no less than i)
        {
            add the word to the list in the dictionary at a key
            being the beginning of the word of length i
        }

    }

}

store contents of the dictionary to the file

答案 2 :(得分:2)

也许你正在寻找类似的东西:

    #!/usr/bin/env python
    def match_prefix(pfx,seq):
        '''return subset of seq that starts with pfx'''
        results = list()
        for i in seq:
            if i.startswith(pfx):
                results.append(i)
        return results

    def extract_prefixes(lngth,seq):
        '''return all prefixes in seq of the length specified'''
        results = dict()
        lngth += 1
        for i in seq:
            if i[0:lngth] not in results:
                results[i[0:lngth]] = True
        return sorted(results.keys())

    def gen_prefix_indexed_list(depth,seq):
        '''return a dictionary of all words matching each prefix
           up to depth keyed on these prefixes'''
        results = dict()
        for each in range(depth):
            for prefix in extract_prefixes(each, seq):
                results[prefix] = match_prefix(prefix, seq)
        return results


    if __name__ == '__main__':
        words='''Apple Ape Arc Abraid Bridge Braide Bray Boolean'''.split()
        test = gen_prefix_indexed_list(2, words)
        for each in sorted(test.keys()):
            print "%s:\t\t" % each,
            print ' '.join(test[each])

也就是说,您希望生成所有前缀,这些前缀出现在您将指定的一个和一个数字之间的单词列表中(在此示例中为2)。然后,您希望生成与这些前缀相匹配的所有单词的索引。

我确信有更优雅的方法可以做到这一点。对于一个快速且易于解释的方法,我刚刚通过简单的自下而上的功能分解来构建它。最终结果值是每个匹配给定前缀的列表,然后我们从函数开始从我们的输入中过滤掉这样的匹配。如果最终结果键是我们输入中出现的1和N之间的所有前缀,那么我们有一个函数来提取它们。那我们的规格。是一个非常简单的嵌套循环。

当然这个嵌套循环可能是个问题。这些事情通常等同于O(n ^ 2)效率。如图所示,这将迭代原始列表C * N * N次(C是表示长度为1,2的前缀的常数;等等;而N是列表的长度)。

如果这种分解提供了所需的语义,那么我们可以考虑提高效率。显而易见的方法是懒惰地生成字典键,因为我们在列表上迭代一次...对于每个单词,对于每个前缀长度,生成键...将此单词附加到存储在该键的列表/值。继续下一个词。

还有一个嵌套循环...但它是每个键/前缀长度的短循环。这种替代设计的优点是允许我们迭代任何可迭代的单词列表,而不仅仅是内存列表。因此,我们可以迭代文件的行,从数据库查询生成的结果等,而不会产生将整个原始单词列表保留在内存中的内存开销。

当然我们仍然将字典存储在内存中。但是,我们也可以改变它,将逻辑与输入和存储分离。当我们将每个输入附加到各种前缀/键值时,我们不关心它们是字典中的列表,还是一组文件中的行,或者是从DBM或其他中拉出(并推回)的值键/值存储(例如某种CouchDB或其他“noSQL集群/数据库”。

执行此操作留给读者练习。

答案 3 :(得分:1)

使用this PHP trie implementation可以获得大约50%的费用。它有一些你不需要的东西,它没有“按前缀搜索”的方法,但你可以很容易地写一个。

$trie = new Trie();

$trie->add('Apple',   'Apple');
$trie->add('Ape',     'Ape');
$trie->add('Arc',     'Arc');
$trie->add('Abraid',  'Abraid');
$trie->add('Bridge',  'Bridge');
$trie->add('Braide',  'Braide');
$trie->add('Bray',    'Bray');
$trie->add('Boolean', 'Boolean');

它建立了这样的结构:

Trie Object
(
  [A] => Trie Object
  (
    [p] => Trie Object
    (
      [ple] => Trie Object
      [e] => Trie Object
    )

    [rc] => Trie Object
    [braid] => Trie Object
  )

  [B] => Trie Object
  (
    [r] => Trie Object
    (
      [idge] => Trie Object
      [a] => Trie Object
      (
        [ide] => Trie Object
        [y] => Trie Object
      )
    )

    [oolean] => Trie Object
  )
)

答案 4 :(得分:0)

如果单词在数据库(Access,SQL)中,并且您想要检索以'br'开头的所有单词,则可以使用:

Table Name: mytable
Field Name: mywords

"Select * from mytable where mywords like 'br*'"  - For Access - or

"Select * from mytable where mywords like 'br%'"  - For SQL