2017年5月滴滴笔试编程---1.最长公共子串问题(扩展到最长公共子序列)

这题没做完真是cnm,怪自己智障浪费时间在第二题

1.最长公共子串问题:

最长公共子串的要求是,这段子串在原字符串中都是连续的,例如'abcdfg'和'abdfg',公共子串为dfg。

原题为:给定几组单词,要求使用T9拼音输入,每个单词输入的数字记作A[i],然后再给出一个数字序列B,找出A中和B最相似的那个单词。相似度定义为最长公共子串长度。

最长公共子串查询的代码如下:

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)

方法摘自:http://blog.csdn.net/wateryouyo/article/details/50917812#

2.最长公共子序列问题:

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

得到输出结果:

 

posted @ 2017-05-07 21:27  koliverpool  阅读(216)  评论(0编辑  收藏  举报