发布时间:2019-09-22整理:admin阅读:
如果我们记字符串Xi和Yj的LCS的长度为c[i,j],我们可以递归地求c[i,j]:
/ 0 if i<0 or j<0
c[i,j]= c[i-1,j-1]+1 if i,j>=0 and xi=xj
\ max(c[i,j-1],c[i-1,j] if i,j>=0 and xi≠xj
上面的公式用递归函数不难求得。但从前面求Fibonacci第n项(本面试题系列第16题)的分析中我们知道直接递归会有很多重复计算,我们用从底向上循环求解的思路效率更高。
为了能够采用循环求解的思路,我们用一个矩阵(参考代码中的LCS_length)保存下来当前已经计算好了的c[i,j],当后面的计算需要这些数据时就可以直接从矩阵读取。另外,求取c[i,j]可以从c[i-1,j-1]、c[i,j-1]或者c[i-1,j]三个方向计算得到,相当于在矩阵LCS_length中是从c[i-1,j-1],c[i,j-1]或者c[i-1,j]的某一个各自移动到c[i,j],因此在矩阵中有三种不同的移动方向:向左、向上和向左上方,其中只有向左上方移动时才表明找到LCS中的一个字符。于是我们需要用另外一个矩阵(参考代码中的LCS_direction)保存移动的方向。
参考代码如下:
// directions of LCS generationenum decreaseDir {kInit = 0, kLeft, kUp, kLeftUp};/////////////////////////////////////////////////////////////////////////////// Get the length of two strings' LCSs, and print one of the LCSs// Input: pStr1 - the first string// pStr2 - the second string// Output: the length of two strings' LCSs/////////////////////////////////////////////////////////////////////////////int LCS(char* pStr1, char* pStr2){if(!pStr1 || !pStr2)return 0;size_t length1 = strlen(pStr1);size_t length2 = strlen(pStr2);if(!length1 || !length2)return 0;size_t i, j;// initiate the length matrixint **LCS_length;LCS_length = (int**)(new int[length1]);for(i = 0; i < length1; ++ i)LCS_length[i] = (int*)new int[length2];for(i = 0; i < length1; ++ i)for(j = 0; j < length2; ++ j)LCS_length[i][j] = 0;欢迎分享转载→ 程序员面试题精选100题(20)-最长公共子串[算法](2)