问题描述:
最长公共子序列(LongestCommonSubsequence,LCS)的问题描述为:给定两个字符串(或数字序列)A和B,求一个字符串,使得这个字符串是A和B的最长公共部分(子序列可以不连续)。如样例所示,字符串“sadstory”与“adminsory”的最长公共子序列为“adsory”,长度为 6。
思路:
暴力的解法:设字符串A和B的长度分别是n和m,那么对两个字符串中的每个字符,分别有选与不选两个决策,而得到两个子序列后,比较两个子序列是否相同又需要 O(max(m,n)),这样总复杂度就会达到O(2"+xmax(m,n)),无法承受数据大的情况。直接来看动态规划的做法(下文的LCS均指最长公共子序列)。令 dp[i][j]表示字符串A的i号位和字符串B的j号位之前的LCS长度(下标从1开始),如 dp[4][5]表示“sads”与“admin”的 LCS 长度。那么可以根据 A[i]和 B[]的情况,分为两种决策:
① 若 A[] = B[j],则字符串 A 与字符串 B的 LCS 增加了1位,即有 dp[i][j]=dp[i-1][j-1]+1。例如,样例中 dp[4][6]表示“sads”与“admins”的 LCS 长度,比较 A[4]与 B[6],发现两者都是's',因此 dp[4][6]就等于 dp[3][5]加1,即为 3。
② 若 A[]!= B[],则字符串A的i号位和字符串B的j号位之前的 LCS 无法延长,因此 dp[i][]将会继承 dp[i-1][]与 dp[i][j-1]中的较大值,即有 dp[i][]=max{dp[i-1][j],dp[i][j-1]}。例如,样例中 dp[3][3]表示“sad”与“adm”的 LCS 长度,我们比较 A[3]与 B[3],发现'd'不等于'㎡',这样 dp[3][3]无法再原先的基础上延长,因此继承自“sa”与“adm”的LCSsad”与“ad”的 LCS 中的较大值,即“sad”与“ad”的 LCS 长度--2.