序列比对的递归代码方法

时间:2013-11-20 21:14:03

标签: recursion bioinformatics

我正在寻找序列比对问题的递归代码。在搜索之后我找到了Needleman Wunsch算法,但矩阵表的构建是用两个for循环实现的,除了我找不到任何在正常时间内完成这个技巧的递归代码。有关递归代码实现的任何想法吗? 谢谢!

2 个答案:

答案 0 :(得分:2)

为什么需要递归算法?

看起来序列对齐问题可以通过动态编程来解决 - 这就是Needleman Wunsch算法正在做的事情。在维基百科页面(http://en.wikipedia.org/wiki/Needleman-Wunsch_algorithm)中,有一个解决问题的复发。这个一个递归解决方案。但是,此递归解决方案反复执行相同的子问题计算。动态编程解决方案通过解决问题自下而上,并通过两个for循环存储计算以供将来查找(memoization)。

答案 1 :(得分:2)

缓存的递归实现

索引变得有点乱,因为我在基于0的数组中使用字符串的长度和as 界。但这很接近这与复发有多接近。 以二次方式分配堆栈帧 然而,对于不支持尾调用的VM而言,这不是一个好主意 以及不是尾递归的实现。

运行时间: O(n * m)

public static int solveWithCache(String n, String m) {
  String paddedN = " " + n; //makes some indexing easier if we pad.
  String paddedM = " " + m;

  int[][] cache = new int[paddedN.length()][paddedM.length()];

  for(int[] row : cache)
    Arrays.fill(row, Integer.MIN_VALUE);

  return solveWithCacheCompute(paddedN, paddedM, paddedN.length()-1, paddedM.length()-1, cache);
}

private static int solveWithCacheCompute(String n, String m, int i, int j, int[][] cache) {
  if(i == 0 && j == 0) return 0;
  if(cache[i][j] != Integer.MIN_VALUE) return cache[i][j];
  if(i == 0) return (j) * gapPenalty;
  if(j == 0) return (i) * gapPenalty;

  int matchScore = (n.charAt(i) == m.charAt(j)) ? matchBenefit : mismatchPenalty;

  int leaveIt = solveWithCacheHelper(n, m, i-1, j-1, cache) + matchScore;
  int addGapN = solveWithCacheHelper(n, m, i-1, j, cache) + gapPenalty;
  int addGapM = solveWithCacheHelper(n, m, i, j-1, cache) + gapPenalty;

  return Math.max(leaveIt, Math.max(addGapN, addGapM));
}

迭代实现

(轻松比较) 典型的DP风格。尽管看那些索引;他们很棘手。

public static int solve(String n, String m) {
  int nlen = n.length();
  int mlen = m.length();
  int[][] maxAlign = new int[nlen + 1][mlen + 1];

  for(int q = 0; q <= nlen; q++) 
    maxAlign[q][0] = q * gapPenalty;

  for(int r = 0; r <= mlen; r++) 
    maxAlign[0][r] = r * gapPenalty;

  for(int i = 1; i <= nlen; i++) {
    for(int j = 1; j <= mlen; j++) {
        int matchScore = (n.charAt(i-1) == m.charAt(j-1)) ? matchBenefit : mismatchPenalty;

        int leaveIt = maxAlign[i-1][j-1] + matchScore;
        int addGapN = maxAlign[i-1][j] + gapPenalty;
        int addGapM = maxAlign[i][j-1] + gapPenalty;

        maxAlign[i][j] = Math.max(leaveIt, Math.max(addGapN, addGapM));
    }
  }

  return maxAlign[nlen][mlen];
}