【问题标题】:Counting the number of different 5 characters substrings inside a string计算字符串中不同的 5 个字符子字符串的数量
【发布时间】:2014-08-14 00:52:23
【问题描述】:

给定一个字符串,我想计算其中有多少个 len = 5 的子字符串。

例如:输入:“ABCDEFG” 输出:3

而且我不确定在 python 中执行此操作的最简单快捷的方法应该是什么。有什么想法吗?

更新:

我只想计算不同的子字符串。

输入:“AAAAAA” 子字符串:2 次“AAAAA” 输出:1

【问题讨论】:

  • 您识别的三个子字符串是什么?
  • 这看起来像是 N-GRAM 的工作 :) 好吧,我想我假设您想要子字符串组合,如果您只想计算它们,那么简单的数学就可以了
  • 在我的示例中,3 个子字符串是“ABCDE”、“BCDEF”和“CDEFG”。这不是字谜。
  • 该更新使这个问题变得更加有趣:) 我想知道最终什么是最有效的方法。
  • 嗯,我很喜欢和你们一起打高尔夫球... :-p

标签: python algorithm


【解决方案1】:
>>> n = 5
>>> for s in 'ABCDEF', 'AAAAAA':
...     len({s[i:i+n] for i in range(len(s)-n+1)})
... 
2
1

【讨论】:

  • 您的解决方案在 14846650 len 字符串中只用了 2.37 秒。最好的。谢谢o/
  • 现在,这就是 Python 面试中最适合的答案。让我看看我能不能打开它。外循环只是为了测试这两个例子。内部语句使用 {} 从内部列表推导的输出中构造一个集合。该列表是通过遍历字符串并从 0 开始拉出 n 个元素直到到达 len() - n 来构建的。通过构建集合,您总是会得到独特的元素。聪明的方法:)
  • @JasonSperske:它是一个生成器表达式,而不是一个列表推导式,也就是说,它应该等同于:S = set()for i in range(len(s)-n+1): S.add(s[i:i+n])——这里没有理由创建一个中间列表。跨度>
【解决方案2】:

要获取子字符串,您可以像这样使用NLTK

>>> from nltk.util import ngrams
>>> for gram in ngrams("ABCDEFG", 5):
...     print gram
... 
('A', 'B', 'C', 'D', 'E')
('B', 'C', 'D', 'E', 'F')
('C', 'D', 'E', 'F', 'G')

您可以应用Counter,然后像这样获得唯一的 n-gram(及其频率):

>>> Counter(ngrams("AAAAAAA", 5))
Counter({('A', 'A', 'A', 'A', 'A'): 3})

【讨论】:

    【解决方案3】:

    使用列表理解(代码高尔夫)

    findSubs=lambda s,v:[''.join([s[i+j] for j in range(v)]) for i,x in enumerate(s) if i<=len(s)-v]
    findCount=lambda s,v:len(findSubs(s,v))
    
    print findSubs('ABCDEFG', 5)  #returns ['ABCDE', 'BCDEF', 'CDEFG']
    print findCount('ABCDEFG', 5) #returns 3
    

    更新

    对于您的更新,您可以将上面的列表转换为一个集合,再转换为一个列表,然后对字符串进行排序。

    findUnique=lambda s,v:sorted(list(set(findSubs(s,v))))
    findUniqueCount=lambda s,v:len(findUnique(s,v))
    
    print findUnique('AAAAAA', 5)      #returns ['AAAAA']
    print findUniqueCount('AAAAAA', 5) #returns 1
    

    【讨论】:

    • 我喜欢你的方法,它使用 Python 内置函数,我认为它与我的性能相同。
    【解决方案4】:

    就是长度减4:

    def substrings(s):
        return len(s) - 4
    

    这是真的,因为您可以为第一个、第二个、...、倒数第五个字符创建一个子字符串作为子字符串的第一个字母。

    【讨论】:

      【解决方案5】:

      一般的解决方案可能是:

      def count(string, nletters):
        return max(0, len(string) - nletters + 1)
      

      根据您的示例,哪个有用例:

      print count("ABCDEFG", 5)
      

      【讨论】:

        【解决方案6】:
        >>> how_much = lambda string, length: max(len(string) - length + 1, 0)
        >>> how_much("ABCDEFG", 5)
        3
        

        【讨论】:

        • "应该有一种——最好只有一种——明显的方法。", PEP20。创建命名函数的明显方法是def
        【解决方案7】:

        我很确定 python 不是一种很好的语言,但是如果你想要找到的不同子字符串的长度不是像 5 那样小,而是像 1000 这样大,而你的主字符串很长,那么线性您的问题的时间解决方案是构建一个后缀树,您可以在线阅读它们。长度为 n 的字符串的后缀树可以在 O(n) 时间内构建,并且遍历树也需要 O(n) 时间,通过遍历树的更高级别,您可以计算特定长度的所有不同子字符串,无论您想要的子字符串的长度如何,也都在 O(n) 时间内。

        【讨论】:

          猜你喜欢
          • 2017-10-20
          • 2023-04-06
          • 1970-01-01
          • 1970-01-01
          • 2023-03-28
          • 1970-01-01
          • 2021-01-24
          • 2014-04-17
          相关资源
          最近更新 更多