python实现求字符串最长公共子串

xiaoxiao2021-02-28  127

本文主要参考http://www.cnblogs.com/ider/p/longest-common-substring-problem-optimization.html的讲解,本人自己用python实现了一下暴力法,动态规划。

# coding: utf-8 # ## 最长公共子串问题 # # ### 暴力法求解 VS 动态规划 # # ### 参考自http://www.cnblogs.com/ider/p/longest-common-substring-problem-optimization.html # # ## 方法一:暴力法求解 # ### 时间复杂度(o^3),空间复杂度(1) # In[2]: get_ipython().magic('pdb on') # In[1]: import numpy as np # In[18]: # 获取字符串str1和str2最长公共子串的长度与起始位置 def getLongestSubstring(str1,str2): longest=0 start_pos1=-1 start_pos2=-1 compares=0 # 记录比较次数 for i in range(len(str1)): for j in range(len(str2)): length=0 m=i n=j while str1[m]==str2[n]: compares+=1 length+=1 m+=1 n+=1 if (m>=len(str1))|(n>=len(str2)): break if longest<length: compares+=1 longest=length start_pos1=i start_pos2=j return longest,start_pos1,start_pos2,compares # ## 方法二:动态规划 # ### 未优化时,时间复杂度(o^2),空间复杂度(o^2) # In[17]: # 通过动态规划的方法优化求解最长公共子串 def getLongestSubstring_dp(str1,str2): str1_len=len(str1) str2_len=len(str2) compares=0 if (str1_len==0)|(str2_len)==0: return -1 # 定义一个二维数据记录最长子串长度 m=np.zeros([str1_len,str2_len],dtype=np.int) for j in range(str2_len): compares+=1 m[0][j]=1 if str1[0]==str2[j] else 0 for i in range(1,str1_len): compares+=1 m[i][0]=1 if str1[i]==str2[0] else 0 for j in range(1,str2_len): compares+=1 m[i][j]=m[i-1][j-1]+1 if str1[i]==str2[j] else 0 # 寻找矩阵中最大的数,也就是最长公共子串的长度 longest=0 start_pos1=-1 start_pos2=-1 for i in range(str1_len): for j in range(str2_len): if longest<m[i][j]: longest=m[i][j] start_pos1=i-longest+1 start_pos2=j-longest+1 return longest,start_pos1,start_pos2,compares # ### 优化后,时间复杂度(o^2),空间复杂度(n) # In[16]: def getLongestSubstring_dp2(str1,str2): str1_len=len(str1) str2_len=len(str2) if (str1_len==0)|(str2_len==0): return -1 start_pos1=0 start_pos2=0 longest=0 compares=0 m=np.zeros([2,str2_len],dtype=np.int) # 只用两行就可以计算最长子串长度 for j in range(str2_len): if str1[0]==str2[j]: compares+=1 m[0][j]=1 if longest==0: longest=1 start_pos1=0 start_pos2=j for i in range(1,str1_len): # 通过且运算计算出当前行和先前行 cur=int((i&1)==1) pre=int((i&1)==0) if str1[i]==str2[0]: compares+=1 m[cur][0]=1 if longest==0: longest=1 start_pos1=i start_pos2=0 for j in range(1,str2_len): if str1[i]==str2[j]: compares+=1 m[cur][j]=m[pre][j-1]+1 if longest<m[cur][j]: longest=m[cur][j] start_pos1=i-longest+1 start_pos2=j-longest+1 return longest,start_pos1,start_pos2,compares # ## 测试 # In[19]: str1='abcababdcababc' str2='ababc' length,s1,s2,com=getLongestSubstring(str1,str2) print(length,s1,s2,com) length,s1,s2,com=getLongestSubstring_dp(str1,str2) print(length,s1,s2,com) length_3,s1_3,s2_3,com_3=getLongestSubstring_dp2(str1,str2) print(length,s1,s2,com)
转载请注明原文地址: https://www.6miu.com/read-20283.html

最新回复(0)