Algorithm 字符串算法问题-单词开头

Algorithm 字符串算法问题-单词开头,algorithm,string,Algorithm,String,我有一个问题,我不太确定如何在不走低效之路的情况下解决它。假设我有一个单词列表: 苹果 类人猿 弧 艾布拉德 桥 编织 布雷 布尔值 我想做的是处理这个列表,得到每个单词开头的深度,例如 苹果、猿、弧、艾布拉德 ab-亚伯拉罕 氩弧 美联社-苹果,猿 b-桥,辫子,布雷,布尔 Bridge、BRIDE、Bray 布尔型 有什么想法吗?你可以使用结构 (root) / a - b - r - a - i - d / \ \

我有一个问题,我不太确定如何在不走低效之路的情况下解决它。假设我有一个单词列表:

  • 苹果
  • 类人猿
  • 艾布拉德
  • 编织
  • 布雷
  • 布尔值
我想做的是处理这个列表,得到每个单词开头的深度,例如

  • 苹果、猿、弧、艾布拉德
  • ab-亚伯拉罕
  • 氩弧
  • 美联社-苹果,猿
  • b-桥,辫子,布雷,布尔
  • Bridge、BRIDE、Bray
  • 布尔型
有什么想法吗?

你可以使用结构

       (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
使用将使你达到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
  )
)

如果单词位于数据库(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

我不知道你在想什么,当你说“效率低下的途径”时,但我想到了非常明显的解决方案(可能就是你正在考虑的那个)。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

也许您正在寻找类似于:

    #!/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])
也就是说,您希望生成单词列表中的所有前缀,这些前缀介于1和您将指定的某个数字之间(本例中为2)。然后,您需要生成与这些前缀中的每一个匹配的所有单词的索引

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

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

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

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

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


实现这一点留给读者作为练习。

您想以某种方式生成一组所有开头,并将开头与单词关联,还是仅仅能够找到某个给定开头的所有单词?生成一组。我正在做的是获取一个包含单词列表的文本文件,我想输出的是类似于我上面发布的内容。Trie数据结构对于类似的事情看起来很有用,但我确实可以在处理输入、生成输出方面使用帮助,而不是如何存储它。