zoukankan      html  css  js  c++  java
  • LCS算法学习

    LCS的定义

    • 最长公共子序列,即Longest Common Subsequence,LCS。
    • 一个序列S任意删除若干个字符得到新序列T,则T叫做S的子序列;
    • 两个序列X和Y的公共子序列中,长度最长的那个,定义为X和Y的最长公共子序列。
    1. 字符串13455与245576的最长公共子序列为455
    2. 字符串acdfg与adfc的最长公共子序列为adf
    • 注意区别最长公共子串(Longest Common Substring)
    1. 最长公共字串要求连续

    LCS的意义

    • 求两个序列中最长的公共子序列算法,广泛的应用在图形相似处理、媒体流的相似比较、计算生物学方面。生物学家常常利用该算法进行基因序列比对,由此推测序列的结构、功能和演化过程。
    • LCS可以描述两段文字之间的“相似度”,即它们的雷同程度,从而能够用来辨别抄袭。另一方面,对一段文字进行修改之后,计算改动前后文字的最长公共子序列,将除此子序列外的部分提取出来,这种方法判断修改的部分,往往十分准确。简而言之,百度知道、百度百科都用得上。

    LCS的记号

    • 字符串X,长度为m,从1开始数;
    • 字符串Y,长度为n ,从1开始数;
    • Xi=﹤x1,⋯,xi﹥即X序列的前i个字符 (1≤i≤m)(Xi不妨读作“字符串X的i前缀”)
    • Yj=﹤y1,⋯,yj﹥即Y序列的前j个字符 (1≤j≤n) (字符串Y的j前缀);
    • LCS(X , Y) 为字符串X和Y的最长公共子序列,即为Z=﹤z1,⋯,zk﹥。
    1. 注:不严格的表述。事实上,X和Y的可能存在多个子串,长度相同并且最大,因此,LCS(X,Y)严格的说,是个字符串集合。即:Z∈ LCS(X , Y) .

    LCS解法的探索: xm=yn

    • 若xm=yn(最后一个字符相同),则:Xm与Yn的最长公共子序列Zk的最后一个字符必定为xm(=yn)。
    1. zk=xm=yn
    2. LCS(Xm , Yn) = LCS(Xm-1 , Yn-1) + xm

    结尾字符相等,则LCS(Xm,Yn)=LCS(Xm-1,Yn-1)+xm

     

    LCS解法的探索:xm≠yn

    • 若xm≠yn,则:要么LCS(Xm,Yn)=LCS(Xm-1, Yn),要么LCS(Xm,Yn)=LCS(Xm, Yn-1)。
    • 证明:令Zk=LCS(Xm,Yn);由于xm≠yn则zk≠xm与zk≠yn至少有一个必然成立,不妨假定zk≠xm(zk≠yn的分析与之类似)。
    1. 因为zk≠xm,则最长公共子序列Zk是Xm-1和Yn得到的,即: Zk =LCS(Xm-1,Yn)
    2. 同理,若zk≠yn,则Zk =LCS(Xm,Yn-1)
    • 即,若xm≠yn,则:
    1. LCS(Xm,Yn)= max{LCS(Xm-1,Yn),LCS(Xm,Yn-1)}

     

    LCS分析总结

     

    显然,属于动态规划问题。

    算法中的数据结构:长度数组

    • 使用二维数组C[m,n]
    • c[i,j]记录序列Xi和Yj的最长公共子序列的长度。
    1. 当i=0或j=0时,空序列是Xi和Yj的最长公共子序列,故c[i,j]=0。

     

    算法中的数据结构:方向变量

    • 使用二维数据B[m,n],其中,b[i,j]标记c[i,j]的值是由哪一个子问题的解达到的。即c[i,j]是由c[i-1,j-1]+1或者c[i-1,j]或者c[i,j-1]的哪一个得到的。取值范围为Left,Top,LeftTop三种情况。

    实例

    • X=< A,B,C,B,D,A,B >
    • Y=< B,D,C,A,B,A >

     

    进一步思考的问题

    • 方向数组b是完全可以省略的:
    1. 数组元素c[i,j]的值仅由c[i-1,j-1],c[i-1,j]和c[i,j-1]三个值之一确定,因此,在计算中,可以临时判断c[i,j]的值是由c[i-1,j-1],c[i-1,j]和c[i,j-1]中哪一个数值元素所确定,代价是Ο(1)时间。
    • 若只计算LCS的长度,则空间复杂度为min(m, n)。
    1. 在计算c[i,j]时,只用到数组c的第i行和第i-1行。因此,只要用2行的数组空间就可以计算出最长公共子序列的长度。

    最大公共子序列的多解性:求所有的LCS

     

    • 当xm≠yn时:

           若LCS(Xm-1,Yn)=LCS(Xm,Yn-1),会导致多解:有多个最长公共子序列,并且它们的长度相等。

    • B的取值范围从1,2,3扩展到1,2,3,4
    • 广度优先遍历

     

    LCS的应用:最长递增子序列LIS

    • Longest Increasing Subsequence
    • 给定一个长度为N的数组,找出一个最长的单调递增子序列。
    • 例如:给定数组 {5, 6, 7, 1, 2, 8},则其最长的单调递增子序列为{5,6,7,8},长度为4。
    1. 分析:其实此LIS问题可以转换成最长公子序列问题,为什么呢?

    使用LCS解LIS问题

    • 原数组为A {5, 6, 7, 1, 2, 8}
    • 排序后:A’{1, 2, 5, 6, 7, 8}
    • 因为,原数组A的子序列顺序保持不变,而且排序后A’本身就是递增的,这样,就保证了两序列的最长公共子序列的递增特性。如此,若想求数组A的最长递增子序列,其实就是求数组A与它的排序数组A’的最长公共子序列。
    1. 此外,本题也可以直接使用动态规划来求解
  • 相关阅读:
    POJ 2068 Nim(博弈论)
    POJ 2311 Cutting Game (Multi-Nim)
    CodeForces 144B Meeting
    ZUFEOJ 2147 07染色带谜题
    CodeForces 779E Bitwise Formula
    CodeForces 779D String Game
    CodeForces 779C Dishonest Sellers
    CodeForces 779B Weird Rounding
    CodeForces 779A Pupils Redistribution
    HRBUST 1313 火影忍者之~静音
  • 原文地址:https://www.cnblogs.com/zhaojihui/p/6753950.html
Copyright © 2011-2022 走看看