在字符串中找到相同的部分

时间:2012-06-20 04:56:04

标签: python genome

我有一个字符串,如:abcgdfabc

我想做以下事情: input:一个字符串,例如:

abcgdfabc

输出:一个字典(键是“字”,值是它显示的时间),

abc:2
gdf:1

单词是“单词”的最大长度,它应该是贪婪的匹配。

我花了很多时间,并且无法弄明白。 字符串超过5000,它是一个基因组,我们想找出它的关系,我们第一次找到这样的字典以使数据更清晰,有帮助。

3 个答案:

答案 0 :(得分:2)

此正则表达式查找字母数字组,可选地跟随任意数量的其他字符,然后再单独查找。然后它重复此列表并删除重复项,并为您提供这些字符组及其出现次数:

import re

s = "eg,abcgdfabc"
for word in set(re.findall(r'(\w+)(\w*?\1)+', s)):
    print word, s.count(word)

打印

abc 2

但是,如果我们不确切知道一个单词是什么,那么它会在下面的字符串中找到一个重复单词,尽管还有另一个候选单词:

abcdeabcecd
abc  abc    <- this will be found
  cd     cd <- this won't be found

答案 1 :(得分:1)

这是一个丑陋的解决方案:

def parse(s,L=None):
    do_return=L is None
    if(not s):
        return
    if(do_return):
        L=[]
    substr=s[0]
    for i in range(1,len(s)-1):
        if s[:i] in s[i:]:
            substr=s[:i]
        else:
            L.append(substr)
            parse(s.replace(substr,''),L=L)
            break
    else:
        L.append(s)

    if(do_return):
        LL=[(ss,s.count(ss)) for ss in L] #Count the number of times each substring appears
        LLL=[]
        #Now some of our (unmatched) substrings will be adjacent to each other.
        #We should merge all adjacent unmatched strings together.
        while LL:
            LLL.append(LL.pop(0))
            while LLL[-1][1] == 1 and LL: #check if next is unmatched
                if(LL[0][1]==1): #unmatched, merge and remove
                    LLL[-1]=(LLL[-1][0]+LL[0][0],1)
                    LL.pop(0)
                else: #matched, keep on going.
                    break
        d={}
        for k,v in LLL:
            d[k]=v

        return d


S='eg,abcgdfabc'
print parse(S)  #{ 'e':1, 'g':2, ',':1, 'abc': 2, 'df', 1}

当然,这并不像你期望的那样,因为g匹配两次(因为它是贪婪的)......

如果你总是希望以3个为一组进行迭代,那么这将变得更容易(更漂亮):

from collections import defaultdict
def parse(s,stride=3):
    d=defaultdict(lambda:0)
    while s:
        key=s[:stride]
        d[key]+=1
        s=s[stride:]

    #if you need a regular dictionary:  dd={}; dd.update(d); return dd      
    return d

答案 2 :(得分:0)

如果您使用的是Python 2.7 +

>>> from itertools import islice
>>> from collections import Counter
>>> def split_steps(step, sequence):
...    it = iter(sequence)
...    bits = ''.join(islice(it,step))
...    while bits:
...        yield bits
...        bits = ''.join(islice(it,step))
...
>>> Counter(split_steps(3,'abcdgfabc')).most_common()
[('abc', 2), ('dgf', 1)]