详解Python最长公共子串和最长公共子序列的实现

最长公共子串(The Longest Common Substring)

LCS问题就是求两个字符串最长公共子串的问题。解法就是用一个矩阵来记录两个字符串中所有位置的两个字符之间的匹配情况,若是匹配则为1,否则为0。然后求出对角线最长的1的序列,其对应的位置就是最长匹配子串的位置。

def find_lcsubstr(s1, s2):
 m=[[0 for i in range(len(s2)+1)] for j in range(len(s1)+1)] #生成0矩阵,为方便后续计算,比字符串长度多了一列
 mmax=0  #最长匹配的长度
 p=0 #最长匹配对应在s1中的最后一位
 for i in range(len(s1)):
 for j in range(len(s2)):
  if s1[i]==s2[j]:
  m[i+1][j+1]=m[i][j]+1
  if m[i+1][j+1]>mmax:
   mmax=m[i+1][j+1]
   p=i+1
 return s1[p-mmax:p],mmax  #返回最长子串及其长度

print find_lcsubstr('abcdfg','abdfg')

运行得到输出:('dfg',3)

最长公共子序列 (The Longest Common Subsequence)

子串要求字符必须是连续的,但是子序列就不是这样。最长公共子序列是一个十分实用的问题,它可以描述两段文字之间的“相似度”,即它们的雷同程度,从而能够用来辨别抄袭。对一段文字进行修改之后,计算改动前后文字的最长公共子序列,将除此子序列外的部分提取出来,这种方法判断修改的部分,往往十分准确。
        解法就是用动态回归的思想,一个矩阵记录两个字符串中匹配情况,若是匹配则为左上方的值加1,否则为左方和上方的最大值。一个矩阵记录转移方向,然后根据转移方向,回溯找到最长子序列。

import numpy
def find_lcseque(s1, s2):
 # 生成字符串长度加1的0矩阵,m用来保存对应位置匹配的结果
 m = [ [ 0 for x in range(len(s2)+1) ] for y in range(len(s1)+1) ]
 # d用来记录转移方向
 d = [ [ None for x in range(len(s2)+1) ] for y in range(len(s1)+1) ] 

 for p1 in range(len(s1)):
 for p2 in range(len(s2)):
  if s1[p1] == s2[p2]:      #字符匹配成功,则该位置的值为左上方的值加1
  m[p1+1][p2+1] = m[p1][p2]+1
  d[p1+1][p2+1] = 'ok'
  elif m[p1+1][p2] > m[p1][p2+1]: #左值大于上值,则该位置的值为左值,并标记回溯时的方向
  m[p1+1][p2+1] = m[p1+1][p2]
  d[p1+1][p2+1] = 'left'
  else:              #上值大于左值,则该位置的值为上值,并标记方向up
  m[p1+1][p2+1] = m[p1][p2+1]
  d[p1+1][p2+1] = 'up'
 (p1, p2) = (len(s1), len(s2))
 print numpy.array(d)
 s = []
 while m[p1][p2]:  #不为None时
 c = d[p1][p2]
 if c == 'ok':  #匹配成功,插入该字符,并向左上角找下一个
  s.append(s1[p1-1])
  p1-=1
  p2-=1
 if c =='left': #根据标记,向左找下一个
  p2 -= 1
 if c == 'up':  #根据标记,向上找下一个
  p1 -= 1
 s.reverse()
 return ''.join(s)
print find_lcseque('abdfg','abcdfg')

得到输出结果:

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持我们。

(0)

相关推荐

  • Python实现针对给定字符串寻找最长非重复子串的方法

    本文实例讲述了Python实现针对给定字符串寻找最长非重复子串的方法.分享给大家供大家参考,具体如下: 问题: 给定一个字符串,寻找其中最长的重复子序列,如果字符串是单个字符组成的话如"aaaaaaaaaaaaa"那么满足要求的输出就是a 思路: 这里的思路有两种是我能想到的 (1)从头开始遍历字符串,设置标志位,在往后走的过程中当发现和之前标志位重合的时候就回头检查一下这个新出现的子串是否跟前面字符串或者前面字符串的子串相同,相同则记录该子串并计数加1,直至处理完毕 (2)利用滑窗切

  • python实现对求解最长回文子串的动态规划算法

    基于Python实现对求解最长回文子串的动态规划算法,具体内容如下 1.题目 给定一个字符串 s,找到 s 中最长的回文子串.你可以假设 s 的最大长度为1000. 示例 1: 输入: "babad" 输出: "bab" 注意: "aba"也是一个有效答案. 示例 2: 输入: "cbbd" 输出: "bb" 2.求解 对于暴力求解在这里就不再骜述了,着重介绍如何利用动态规划算法进行求解. 关于动态规划的含

  • Python字符串中查找子串小技巧

    惭愧啊,今天写了个查找子串的Python程序被BS了- 如果让你写一个程序检查字符串s2中是不是包含有s1.也许你会很直观的写下下面的代码: 复制代码 代码如下: #determine whether s1 is a substring of s2 def isSubstring1(s1,s2):     tag = False     len1 = len(s1)     len2 = len(s2)     for i in range(0,len2):         if s2[i] =

  • Python简单实现查找一个字符串中最长不重复子串的方法

    本文实例讲述了Python简单实现查找一个字符串中最长不重复子串的方法.分享给大家供大家参考,具体如下: 刚结束的一个笔试题,很简单,不多说简单贴一下具体的实现: #!usr/bin/env python #encoding:utf-8 ''''' __Author__:沂水寒城 功能:找出来一个字符串中最长不重复子串 ''' def find_longest_no_repeat_substr(one_str): ''''' 找出来一个字符串中最长不重复子串 ''' res_list=[] le

  • Python实现判断一个字符串是否包含子串的方法总结

    本文实例总结了Python实现判断一个字符串是否包含子串的方法.分享给大家供大家参考,具体如下: 1.使用成员操作符 in >>> s='nihao,shijie' >>> t='nihao' >>> result = t in s >>> print result True 2.使用string模块的find()/rfind()方法 >>> import string >>> s='nihao,s

  • 在Python中实现替换字符串中的子串的示例

    假如有个任务: 给定一个字符串,通过查询字典,来替换给定字符中的变量.如果使用通常的方法: >>> "This is a %(var)s" % {"var":"dog"} 'This is a dog' >>> 其实可以使用string.Template类来实现上面的替换 >>> from string import Template >>> words = Template

  • python实现求最长回文子串长度

    给定一个字符串,求它最长的回文子串长度,例如输入字符串'35534321',它的最长回文子串是'3553',所以返回4. 最容易想到的办法是枚举出所有的子串,然后一一判断是否为回文串,返回最长的回文子串长度.不用我说,枚举实现的耗时是我们无法忍受的.那么有没有高效查找回文子串的方法呢?答案当然是肯定的,那就是中心扩展法,选择一个元素作为中心,然后向外发散的寻找以该元素为圆心的最大回文子串.但是又出现了新的问题,回文子串的长度即可能是基数,也可能好是偶数,对于长度为偶数的回文子串来说是不存在中心元

  • Python实现统计给定字符串中重复模式最高子串功能示例

    本文实例讲述了Python实现统计给定字符串中重复模式最高子串功能.分享给大家供大家参考,具体如下: 给定一个字符串,如何得到其中重复模式最高的子字符串,我采用的方法是使用滑窗机制,对给定的字符串切分,窗口的大小从1增加到字符串长度减1,将所有的得到的切片统计结果,在这里不考虑单个字符的重复模式,好了,很简单看具体实现: #!usr/binenv python #encoding:utf-8 ''''' __Author__:沂水寒城 统计一个给定字符串中重复模式数量得到最高重复模式串 '''

  • Python利用正则表达式匹配并截取指定子串及去重的方法

    本文实例讲述了Python利用正则表达式匹配并截取指定子串及去重的方法.分享给大家供大家参考.具体如下: import re pattern=re.compile(r'\| (\d+) \| (\d+) \|') numset=set() all=''' | 29266795 | 533 | | 29370116 | 533 | | 29467495 | 533 | | 29500404 | 533 | | 29500622 | 533 | | 29515964 | 530 | | 295160

  • Python中判断子串存在的性能比较及分析总结

    起步 对于子串搜索,Python提供了多种实现方式:in, find, index, __contains__,对其进行性能比较: import timeit def in_(s, other): return other in s def contains(s, other): return s.__contains__(other) def find(s, other): return s.find(other) != -1 def index(s, other): try: s.index

随机推荐