最长公共子序列

/*
1. 最长公共子序列(LCS)问题
通过构建表格(二维数组),来求两个结构的公共部分有奇效。

2. 最长递增子序列LIS的问题  
设原数组为A  
把原数组递增排序为A'  
求A和A’的最长公共子序列即可。

动态规划,综合上几步计算出的信息,算出下一步的值。
因此需要维护一存储空间。   

参考链接:
http://blog.csdn.net/github_36487770/article/details/66532403
http://blog.csdn.net/lisonglisonglisong/article/details/41596309
*/

function lstd(stra, strb) {
  var n, i, j;
  var dp = [], lst = [];
  var arr = stra.split("");
  var brr = strb.split("");
  var lena = arr.length;
  var lenb = brr.length;
  var LCSArr = [];

  // 构建二维数组,也就是表格 
  for (i = 0; i < lena + 1; i++) {
    dp[i] = [];
    for (j = 0; j < lenb + 1; j++) {
      if (i == 0 || j == 0) dp[i][j] = 0;
      else if (arr[i] === brr[j]) { dp[i][j] = dp[i - 1][j - 1] + 1; }
      else { dp[i][j] = Math.max(dp[i - 1][j], dp[i][j - 1]); }
    }
  }
  var lst = "";

  // 回溯,获取公共子序列
  var traceback = function (i, j, lst) {

    while (i > 0 && j > 0) {
      if (arr[i - 1] === brr[j - 1]) {
        lst += arr[i - 1];
        if (lst.length === dp[lena][lenb]) {
          LCSArr.push(lst.split("").reverse().join(""));
        }
        i--; j--;
      }
      else {
        if (dp[i - 1][j] > dp[i][j - 1]) { --i; }
        else if (dp[i - 1][j] < dp[i][j - 1]) { --j; }
        else {
          traceback(i - 1, j, lst);
          traceback(i, j - 1, lst);
          return;   //千万不要忘了return!!!
        }
      }
    }
  };

  traceback(lena, lenb, lst);
  return {
    length:dp[lena][lenb], //公共子序列的最大长度
    LCS: LCSArr
  }

}
let x = "ABCBDAB";
let y = "BDCABA";

console.log(lstd(x, y).LCS);
posted @ 2017-10-06 18:55  草珊瑚  阅读(215)  评论(0编辑  收藏  举报