LongestCommonSubsequence 最长公共子序列

问题

序列ss的子序列是原序列的子集,元素相对原序列的顺序不变。例如s=[1,2,3]s = [1,2,3]的子序列有

[1,2,3],[1,2],[1,3],[2,3],[1],[2],[3],[][1,2,3],[1,2],[1,3],[2,3],[1],[2],[3],[]

求两个序列s1s_{1}s2s_{2}的最长公共子序列的长度。

解法

设序列ss长度为nn(数组从11开始,范围[1,n][1,n])。设f(i,j)f(i,j)s1=[1,i]s_1 = [1,i]s2=[1,j]s_2 = [1,j]的最长公共子序列的长度,则有状态转移方程:

f(i,j)={0(initialize)i,j[0,n]f(i1,j1)+1(loop)i,j[1,n],s1[i]=s2[j]max(f(i,j1),f(i1,j))(loop)i,j[1,n],s1[i]s2[j]f(i,j) = \begin{cases} 0 & (initialize) & i,j \in [0,n] \\ f(i-1,j-1)+1 & (loop) & i,j \in [1,n], s_1 [i] = s_2 [j] \\ max(f(i,j-1),f(i-1,j)) & (loop) & i,j \in [1,n], s_1 [i] \neq s_2 [j] \end{cases}

(1)(1) 初始化f(i,j)=0f(i,j) = 0

(2)(2)s1[i]=s2[j]s_1 [i] = s_2 [j],则显然两个序列的这个部分是公共的,所以f(i,j)f(i,j)f(i1,j1)f(i-1,j-1)的基础上加11

(3)(3)s1[i]s2[j]s_1 [i] \neq s_2 [j],则两个序列的这个部分不是公共的,所以f(i,j)f(i,j)仍然保持之前的值,为了获取最大值我们会在f(i,j1)f(i,j-1)f(i1,j)f(i-1,j)中选取最大的那个;

f(n,n)f(n,n)即为序列s1s_1s2s_2的最长公共子序列的长度值。该算法的时间复杂度为O(n2)O(n^2)

源码

LongestCommonSubsequence.h

LongestCommonSubsequence.cpp

测试

LongestCommonSubsequenceTest.cpp

Last updated