求最长公共子串

求最长公共子串

  • 最长公共子串最好的算法是动态规划。其次KMP算法也是解决这类方法中比较好的实现。

思路一

  • 最慢方法,两个字符中每个元素都依次比较,如果相同就检测最长相同串。
#思路一,最慢方法,两个字符中每个元素都依次比较,如果相同就检测最长相同串。
str1 = "aabcdefgh"
str2 = "aaabcdef"

# str1 = "aaaaaaabbbbbcccccccccccccdddddddddddd"
# str2 = "bbbaaaaacccccccccccdddddddddddddddddddaaaaaaaaaaaaaaa"

def getMaxsame1(str1,str2):
    compare = 0
    maxcount = 0
    maxsame = set()
    for i,one in enumerate(str1):
        end = i
        for k in range(len(str2)):
            compare += 1
            while end<len(str1) and k<len(str2) and str1[end]==str2[k]:
                compare +=1
                end += 1
                k += 1
            if end != i: #进入过循环体
                compare -= 1 #取出重复记录的一次
                temp = end-i
                if maxcount<temp:
                    maxsame = {str1[i:end]}
                    maxcount = temp
                elif maxcount==temp:
                    maxsame.add(str1[i:end])
                end = i
#     print(compare)
    return maxsame
# getMaxsame(str1,str2)
for i in getMaxsame1(str1,str2):
    print(i,len(i))

思路二

  • 对最短字符建立,字符与索引的k:v对,v为索引范围的列表。如:{a:[a所出现的索引]},依次从最长字符中遍历,匹配出现的索引位置最长的相同串。求出最长公共子串
from collections import defaultdict
#思路二 对最短字符建立,字符与索引的k:v对,v为索引范围的列表。如:{a:[a所出现的索引]},
#依次从最长字符中遍历,匹配出现的索引位置最长的相同串。求出最长公共子串
str1 = "aabcdefgh"
str2 = "aaabcdef"

# str1 = "aaaaaaabbbbbcccccccccccccdddddddddddd"
# str2 = "bbbaaaaacccccccccccdddddddddddddddddddaaaaaaaaaaaaaaa"

def getMaxsame2(str1,str2):
    if len(str1)>len(str2):
        str1,str2 = str2,str1
    indexset = defaultdict(list)
    #从最短字符串中获取字典,进可能的节约空间
    for i,one in enumerate(str1):
        indexset[one].append(i)

    compare = 0 
    maxcount = 0
    maxsame = set()
    
    #遍历最长字符串
    for i,one in enumerate(str2):
        for k in indexset.get(one,[]):
            compare += 1 
            end = i+1
            k += 1
            while end<len(str2) and k<len(str1) and str2[end]==str1[k]:
                compare += 1
                end += 1
                k += 1
            temp = end-i
#             print(temp,i,end,k)
            if maxcount<temp:
                maxsame = {str2[i:end]}
                maxcount = temp
            elif maxcount == temp:
                maxsame.add(str2[i:end])
#     print(compare)
    return maxsame

for i in getMaxsame2(str1,str2):
    print(i,len(i))

思路三

  • 使用动态规划。
  • 建立str1* str2的矩阵,相同赋值1不同赋值0.求右斜线连续为1的最长集合即为最长公共子串
# 思路三,使用动态规划。建立str1* str2的矩阵,相同赋值1不同赋值0.求右斜线连续为1的最长集合即为最长公共子串
str1 = "aabcdefgh"
str2 = "aaabcdef"
def getMaxsame3(str1,str2):
    arr1 = [] #动态规划模拟矩阵
    maxcount = 0;#记录最长字符串的长度
    maxstr = [] #记录所有最长字符串的结束索引
    for n1,v1 in enumerate(str1):
        arr1.append([])
        for n2,v2 in enumerate(str2):
            if v2==v1:
                i = n1 -1
                k = n2 -1
                if i>=0 and k>=0:
                    temp = arr1[i][k]+1
                    arr1[n1].append(temp)
                    if maxcount<temp:
                        maxstr = [(n1,n2)]
                        maxcount = temp
                    elif maxcount==temp:
                        maxstr.append((n1,n2))
                else:
                    arr1[n1].append(1)
                    if maxcount <1:
                        maxstr = [(n1,n2)]
                        maxcount = 1
                    elif maxcount == 1:
                        maxstr.append((n1,n2))
            else:
                arr1[n1].append(0)
    arrdict = {str1[n1+1-maxcount:n1+1] for n1,n2 in maxstr}
    return arrdict,maxcount
getMaxsame3(str1,str2)
  • 2
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值