python3 lcs 最大公共子序列

抛出问题:

  假定字符串 s1 = ‘BDCABA‘, s2 = ‘ABCBDAB‘,求s1和s2的最大公共子序列。

问题分析:

  我们想要求出s1和s2的最大公共子序列,我们可以用c(i,j)表示s1(i)和s2(j)最大公共子序列的长度,

   假定c(i,j) = m,

     如果:s1[ i ]s2[ j ]相等,那么推出c(i,j) = c(i-1,j-1)  + 1,

  如果:s1[ i ] 和 s2[ j ]不相等,那么得到c(i,j) = max(c(i,j-1),c(i-1,j))

  总结为公式就是:

画成表格更清楚,也就是如下图,表格的数即为当前的最大公共子序列的值,箭头即为该结果是怎么得来的

例如第5行,第5列,因为第5列的c和第5行c相等,所以就等于,第4行,第4列的值+1等到2

  得到了这个值列表,就可以通过回溯的方法,从最后一个值,倒着按照箭头的方向,依次记录每个相等的值(也就是方向是左上的值),得到的结果就是我们要求的最终结果

代码实现:

# -*- coding:utf-8  -*-
# 日期:2018/6/9 15:44
# Author:小鼠标
# 求最长公共子序列
from numpy import *
s1 = ‘BDCABA‘
s2 = ‘ABCBDAB‘

def val_list(s1,s2):
    # 两个字符串的长度
    len_s1 = len(s1) + 1
    len_s2 = len(s2) + 1
    # 方向列表
    direction_list = []
    # 生成len_s2+1行len_s1+1列的全0列表
    res = zeros((len_s2,len_s1))
    direction = zeros((len_s2,len_s1))
    # print(res_list)
    for i in range(0, len_s2-1):
        for j in range(0, len_s1-1):
            #判断是否相等
            if s1[j] == s2[i]:
                res[i + 1, j + 1] = res[i, j] + 1
                # 1左上 2 上 3左
                direction[i + 1, j + 1] = 1
            else:
                if res[i + 1, j] > res[i, j + 1]:
                    res[i + 1, j + 1] = res[i + 1, j]
                    direction[i + 1, j + 1] = 3
                else:
                    res[i + 1, j + 1] = res[i, j + 1]
                    direction[i + 1, j + 1] = 2
    return res,direction
res ,direction= val_list(s1,s2)
#方向列表 1左上 2 上 3左
# [[0. 0. 0. 0. 0. 0. 0.]
#  [0. 2. 2. 2. 1. 3. 1.]
#  [0. 1. 3. 3. 2. 1. 3.]
#  [0. 2. 2. 1. 3. 2. 2.]
#  [0. 1. 2. 2. 2. 1. 3.]
#  [0. 2. 1. 2. 2. 2. 2.]
#  [0. 2. 2. 2. 1. 2. 1.]
#  [0. 1. 2. 2. 2. 1. 2.]]

#最大子序列的值列表
# [[0. 0. 0. 0. 0. 0. 0.]
# [0. 0. 0. 0. 1. 1. 1.]
# [0. 1. 1. 1. 1. 2. 2.]
# [0. 1. 1. 2. 2. 2. 2.]
# [0. 1. 1. 2. 2. 3. 3.]
# [0. 1. 2. 2. 2. 3. 3.]
# [0. 1. 2. 2. 3. 3. 4.]
# [0. 1. 2. 2. 3. 4. 4.]]

#回溯 递归求出结果
global s_res
s_res = ‘‘
def Lcs_fun(s,res_list,i,j):
    if res_list[i,j] == 3:
        Lcs_fun(s,res_list,i,j-1)

    elif res_list[i,j] == 2:
        Lcs_fun(s,res_list,i-1,j)

    elif res_list[i,j] == 1:
        Lcs_fun(s,res_list,i-1,j-1)
        global s_res
        s_res += s[i-1]
    else:
        return
Lcs_fun(s2,direction,len(s2),len(s1))
print(s_res)

这块很容易就看晕了,仔细看,应该能看懂

原文地址:https://www.cnblogs.com/7749ha/p/9160868.html

时间: 2024-10-31 06:14:36

python3 lcs 最大公共子序列的相关文章

HDU 1159 Common Subsequence 最大公共子序列

Problem Description A subsequence of a given sequence is the given sequence with some elements (possible none) left out. Given a sequence X = <x1, x2, ..., xm> another sequence Z = <z1, z2, ..., zk> is a subsequence of X if there exists a stri

动态规划(最大公共子序列)

网上关于动态规划的资料很多,看了很多,总结如下: 求原字符串和其反串的最大公共子序列(不是子串,因为可以不连续)的长度(使用动态规划很容易求得) 1)首先是要知道最长公共子序列的长度的动态规划方程 设有字符串a[0...n],b[0...m],下面就是递推公式.字符串a对应的是二维数组num的行,字符串b对应的是二维数组num的列. 2.其次要看的懂求BDCABA与ABCBDAB的最大公共子序列 3.关键代码如下: 1 package com.sxt.bean; 2 3 import java.

ACM最大公共子序列&amp;&amp;回文串

---恢复内容开始--- Description A palindrome is a symmetrical string, that is, a string read identically from left to right as well as from right to left. You are to write a program which, given a string, determines the minimal number of characters to be in

ACM 最大公共子序列

Description A subsequence of a given sequence is the given sequence with some elements (possible none) left out. Given a sequence X = < x1, x2, ..., xm > another sequence Z = < z1, z2, ..., zk > is a subsequence of X if there exists a strictly

hdu1159 最大公共子序列

题意就不用多说了       这道题就是求两个串的最大公共子序列  注意与最大公共子串的区别 最长公共子序列的结构 最长公共子序列的结构有如下表示: 设序列X=<x1, x2, -, xm>和Y=<y1, y2, -, yn>的一个最长公共子序列Z=<z1, z2, -, zk>,则: 1> 若 xm=yn,则 zk=xm=yn,且Zk-1是Xm-1和Yn-1的最长公共子序列: 2> 若 xm≠yn且 zk≠xm ,则 Z是 Xm-1和 Y的最长公共子序列:

经典算法之动态规划--求最大公共子序列

作为新人,之前对C,C++了解的比较少,关于算法方面更是一窍不通,但最近却痴迷上了算法,哪怕是前辈们不屑一顾的东东,我弄明白了后都会欣喜若狂! 今天将遇到的问题和java实现贴出来和同为新人的博友分享,老鸟可以可以直接关网页了. 定义: 子序列:一个给定序列的子序列是再该序列中删去若干元素后得到的序列.即:给定{x1,x2,...,xm}和Z={z1,z2,...,zk},X的子序列是指存在一个严格递增下表序列{i1,i2,...ik} 使得对所有的j=1,2,...k,都有zj=xij.例如:

spoj Longest Common Substring (多串求最大公共子序列)

题目链接: https://vjudge.net/problem/SPOJ-LCS 题意: 最多10行字符串 求最大公共子序列 数据范围: $1\leq |S| \leq100000$ 分析: 让他们都和第一个字符串匹配,算出每个字符串与第一个字符串的,以$i$位置(i指的是在s1中的位置)结尾匹配的最大长度 与其它字符串的匹配取最小值 最后对所有位置取最大值 超时代码:(题限是236ms,这个代码跑2000ms没问题) #include<bits/stdc++.h> #define ll l

最大公共子序列(动规)

问题描述:一个给定序列的子序列是在该序列中删去若干元素后得到的序列.确切地说,若给定序列X= { x1, x2,…, xm},则另一序列Z= {z1, z2,…, zk}是X的子序列是指存在一个严格递增的下标序列 {i1, i2,…, ik},使得对于所有j=1,2,…,k有 Xij=Zj.例如,序列Z={B,C,D,B}是序列X={A,B,C,B,D,A,B}的子序列,相应的递增下标序列为{2,3,5,7}.给定两个序列X和Y,当另一序列Z既是X的子序列又是Y的子序列时,称Z是序列X和Y的公共

Common Subsequence 最大公共子序列问题

Problem Description A subsequence of a given sequence is the given sequence with some elements (possible none) left out. Given a sequence X = <x1, x2, ..., xm> another sequence Z = <z1, z2, ..., zk> is a subsequence of X if there exists a stri