当前位置: 首页 > 知识库问答 >
问题:

查找字符串中最长的重复序列

汤念
2023-03-14

我需要找到字符串中最长的序列,并警告序列必须重复三次或更多次。例如,如果我的字符串是:

fdwaw4helloworld vcdv1c3xcv3xcz1sda21f2sd1ahelloworld gafgfa4564534321fadghelloworld

然后我希望返回值“helloworld”。

我知道有几种方法可以做到这一点,但我面临的问题是,实际的字符串太大了,所以我真的在寻找一种能够及时做到这一点的方法。

共有3个答案

胡飞舟
2023-03-14

让我们从头开始,统计频率,当最频繁的元素出现3次或更多次时,立即停止。

from collections import Counter
a='fdwaw4helloworldvcdv1c3xcv3xcz1sda21f2sd1ahelloworldgafgfa4564534321fadghelloworld'
times=3
for n in range(1,len(a)/times+1)[::-1]:
    substrings=[a[i:i+n] for i in range(len(a)-n+1)]
    freqs=Counter(substrings)
    if freqs.most_common(1)[0][1]>=3:
        seq=freqs.most_common(1)[0][0]
        break
print "sequence '%s' of length %s occurs %s or more times"%(seq,n,times)

结果:

>>> sequence 'helloworld' of length 10 occurs 3 or more times

编辑:如果您觉得您正在处理随机输入,并且公共子字符串应该是小长度的,那么最好从小子字符串开始(如果您需要速度),并在找不到至少出现3次的子字符串时停止:

from collections import Counter
a='fdwaw4helloworldvcdv1c3xcv3xcz1sda21f2sd1ahelloworldgafgfa4564534321fadghelloworld'
times=3
for n in range(1,len(a)/times+1):
    substrings=[a[i:i+n] for i in range(len(a)-n+1)]
    freqs=Counter(substrings)
    if freqs.most_common(1)[0][1]<3:
        n-=1
        break
    else:
        seq=freqs.most_common(1)[0][0]
print "sequence '%s' of length %s occurs %s or more times"%(seq,n,times) 

与上述结果相同。

华季萌
2023-03-14

使用defaultdict对从输入字符串中的每个位置开始的每个子字符串进行计数。OP不清楚是否应该包括重叠匹配,这种暴力方法包括重叠匹配。

from collections import defaultdict

def getsubs(loc, s):
    substr = s[loc:]
    i = -1
    while(substr):
        yield substr
        substr = s[loc:i]
        i -= 1

def longestRepetitiveSubstring(r, minocc=3):
    occ = defaultdict(int)
    # tally all occurrences of all substrings
    for i in range(len(r)):
        for sub in getsubs(i,r):
            occ[sub] += 1

    # filter out all substrings with fewer than minocc occurrences
    occ_minocc = [k for k,v in occ.items() if v >= minocc]

    if occ_minocc:
        maxkey =  max(occ_minocc, key=len)
        return maxkey, occ[maxkey]
    else:
        raise ValueError("no repetitions of any substring of '%s' with %d or more occurrences" % (r,minocc))

印刷品:

('helloworld', 3)
楚望
2023-03-14

这个问题是最长重复子串问题的变体,有一个使用后缀树的O(n)时间算法来解决它。这个想法(正如维基百科所建议的)是构建一个后缀树(时间O(n)),用子代的数量(时间O(n)使用DFS)注释树中的所有节点,然后用at找到树中最深的节点至少三个后代(使用DFS的时间O(n))。这种总体算法需要时间O(n)。

也就是说,众所周知,后缀树很难构建,所以在尝试这个实现之前,您可能希望找到一个为您实现后缀树的Python库。一个快速的谷歌搜索会出现这个库,尽管我不确定这是否是一个好的实现。

另一种选择是将后缀数组与LCP数组结合使用。您可以迭代LCP数组中的相邻元素对,取每对的最小值,并以这种方式存储您找到的最大值。这将对应于重复至少三次的最长字符串的长度,然后您可以从那里读取字符串本身。

有几种简单的算法可用于构建后缀数组(Manber-Myers算法在时间O(n logn)内运行,编码也不太困难),Kasai的算法在时间O(n)内构建LCP数组,编码起来相当简单。

希望这有帮助!

 类似资料:
  • 我在一个文本文件中有一个长字符串(DNA序列,超过20000个字符),我试图找到其中最长的序列,它至少重复了三次。实现这一目标的最佳方式是什么? 我能找到的唯一现有主题是在两个或多个单独的字符串中查找重复,但是如何使用一个长字符串?

  • 我有一个tweet数据库,其中实际的tweet文本在一个名为“text”的字段中。 我想知道如何查询并显示最长的tweet?我一直在想也许.排序或.长度或诸如此类的东西,但我环顾四周,到目前为止还没有找到任何有用的东西。 救命啊!谢谢!

  • 我知道如何使用动态规划来解决 <罢工> 大多数 给定两个字符串的最长公共子串或最长公共子串。然而,对于字符串Y的子串X的最长子序列问题,我很难找到一个解决方案。 查找字符串X的所有子序列并按长度desc排序; 遍历排序的子序列,如果当前子序列是Y的子字符串,则返回子序列。 它可以工作,但运行时间可能会很糟糕。假设X中的所有字符都是唯一的,那么有2^m个子群,其中m是X的长度,我认为检查一个字符串是

  • 问题内容: 这个问题与Python类似-在字典中查找最长(最多单词)键-但我需要纯字符数。 输入示例: 输出: 问题答案: 替代方法,与@jamylak的解决方案一样快,并且使用更多的pythonic: 查看比较:

  • 问题内容: 在字符串数组中找到最长的字符串有一种简便的方法吗? 像什么? 问题答案: var longest = arr.sort(function (a, b) { return b.length - a.length; })[0]; 可能更有效,但仅自Javascript 1.8 / ECMAScript5起可用,并且在较旧的浏览器中默认不可用:

  • 问题是,我试图这么做,但我检查字符串长度的方法不起作用;我能做些什么来修复它?