首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >使用动态规划的最长公共子串

使用动态规划的最长公共子串
EN

Code Review用户
提问于 2016-10-28 18:37:20
回答 1查看 523关注 0票数 2

我编写了一个简短的python脚本,它试图解决使用动态编程技术寻找最长的公共子字符串的问题。它应该是泛化的,这样我就可以插入任意数量的字符串,并找到最长的公共子字符串。

代码语言:javascript
复制
def longest_common_substring(*strings):
    table = defaultdict(int)
    for pos in product(*(range(len(s)) for s in strings)):
        same = len(set(s[i] for s, i in zip(strings, pos))) is 1
        table[pos] = table[tuple(map(lambda n: n - 1, pos))] + 1 if same else 0
    return max(table.items(), key=operator.itemgetter(1))

对于少量短字符串来说,这是很好的,但是空间和时间复杂度肯定会随着较长的字符串而变大。

我从维基百科获得了这一点,而且由于这种方法对于多个更长的字符串来说显然很糟糕(或者我的实现是糟糕的!?),我想知道我能做些什么来改进它?维基百科也有一个通用的后缀树..。我对他们一点也不熟悉,那会是一个更好的方法吗?

而且,如果这是我的实现,我很想知道哪里出了问题,在空间复杂性方面我可以做得更好。

EN

回答 1

Code Review用户

发布于 2016-10-29 15:08:39

很抱歉,我没有仔细检查您的代码,无法发表评论,但考虑到前面提到的问题和您正在使用Py3的事实,我可能会用itertools.accumulate来解决它,例如:

代码语言:javascript
复制
>>> import itertools as it
>>> import operator as op
>>> ss = ["thisishello", "dfdsishdllo", "ashsisdsdsf"]
>>> i, l = max(enumerate(it.accumulate(it.chain([0], zip(*ss)),
...                      lambda x, y: (x+1)*(len(set(y)) == 1))), key=op.itemgetter(1))
>>> i, l, ss[0][i-l:i]
(6, 3, 'sis')

对于任意数量的字符串,应该可以很好地工作,因为它使用生成器,并且不创建任何中间数据结构。

它确实使用了一个事实,即False等同于len(set(y)) == 1的0,但如果这让人不舒服,您可以简单地用1 if len(set(y)) == 1 else 0替换。

注意:我仍然希望itertools.accumulate有一个和functools.reduce一样的初始值参数,这样就避免了chain将初始值转换为可迭代的需要。

票数 1
EN
页面原文内容由Code Review提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://codereview.stackexchange.com/questions/145550

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档