两天来我一直在研究这个并没有找到任何东西所以我决定编写自己的字符串重复检测器。基本上是功能
def findRepetitions (string):
会收到一个字符串并搜索任何重复;返回一个简化为最简单形式的字符串列表。
对于样本,它是:
findRepetitions ("trololololo") --> ["olo"]
findRepetitions ("bookkeeper") ---> ["o", "k", "e"]
findRepetitions ("Hello, Molly") -> ["l", "l"]
findRepetitions ("abcdefgh") -----> []
findRepetitions ("102102102") ----> ["102"]
在第三个例子中,函数返回[“l”,“l”]而不是[“ll”],因为我只想在相邻的字符中搜索重复。
我知道这可能很难,但我很长时间以来一直在考虑这个问题,而且找不到任何明智的解决方案。
答案 0 :(得分:3)
这是一个众所周知的问题:
http://en.wikipedia.org/wiki/Longest_repeated_substring_problem
你可以有效地解决这个问题但是构建一个特里:
http://en.wikipedia.org/wiki/Radix_tree
wiki页面显示了伪代码以及查找和添加节点的示例,这些节点是您需要的唯一功能。 从每个字符开始在trie中插入字符串,例如对于字符串abcd插入abcd,bcd,cd,d。 trie的这个特定实例称为“后缀树”:
http://en.wikipedia.org/wiki/Suffix_tree
每当你遍历已经建立的路径时,你实际上发现了你的字符串中的重复。 现在,您可以在单独的数据结构中列出所有重复,并提取最长的数据(如有必要)。
答案 1 :(得分:1)
您的示例不一致。例如,olo
中的Hello, Molly
不会像`trololololo
中的l那样重复;实例之间有l
个。 trololololo
中的顺序重复是lolo
,lo
,olol
和ol
。你在问一个'贪婪'的算法吗?那么,给定trololololo
,它会返回olol
?
无论如何,这里有一些代码。
from collections import Counter
def find_repetition(p):
""" Returns a lookup dictionary for repetitions. """
lookup = Counter()
while len(p) != 0:
for i in xrange(len(p)):
lookup[p[0:i]] += 1
p = p[1:]
return lookup
def repeats(p):
a = find_repetition(p)
rs = [i for i in a if a[i] > 1][1:]
return [r for r in rs if r*2 in p]
如果你希望它像我描述的那样'贪婪',你必须添加另一个函数来获取重复的结果,并在找到匹配时将字符串剔除。
目前,结果如下:
test = "trololololo", "bookkeeper", "Hello, Molly", "abcdefgh", "102102102"
>>> for i in test:
>>> repeats(i)
['lolo', 'lo', 'olol', 'ol']
['e', 'o', 'k']
['l']
[]
['210', '021', '102']
警告
find_repetition
不是很快,因为它基本上生成字符串的所有长度组合并将它们抛出到Counter对象中。