找到最大的共同子序列

Sno*_*man 1 java algorithm recursion

我有以下代码,由于某些我试图弄清楚的原因,它无法正常工作:

public static int score(String gene1, String gene2){
    char[] a=new char[gene1.length()];
    char[] b=new char[gene2.length()];
    a=gene1.toCharArray();
    b=gene2.toCharArray();
    return score(a, b, 0,0);
}

private static int score(char[] a, char[] b, int i, int j){
    if(a[i]=='\0' || b[j]=='\0')
        return 0;
    else if (a[i]==b[j])
        return 1+score(a, b, i+1, j+1);
    else 
        return max(score(a, b,i+1, j),score(a, b, i, j+1));
}

private static int max (int a, int b){
    if (a<b) return b;
    else return a;
}
Run Code Online (Sandbox Code Playgroud)

这是它失败的地方:

assertEquals(2, GeneAnalysis.score("ACGT","AC")); 
Run Code Online (Sandbox Code Playgroud)

我得到一个IndexOutofBoundsError

有任何想法吗?此外,在提供帮助时,请不要更改方法参数.他们应该是他们的方式.

Tof*_*eer 6

部分原因似乎是C和Java之间的混淆....

if(a[i]=='\0' || b[j]=='\0')
        return 0;
Run Code Online (Sandbox Code Playgroud)

C对字符串有一个空终止符,而Java则没有.而不是检查Java数组的结尾,您将需要使用.length属性...类似于:

   if(i >= a.length || j >= b.length) 
Run Code Online (Sandbox Code Playgroud)

根据评论进行编辑.

真的,你应该就此问一个单独的问题......但这里有一个关于它是如何工作的刺.首先,你使用的是递归,这是一个棘手的概念.维基百科可能可以帮助您了解递归的基础知识.

以下代码更接近于我将如何编写它,其中的注释向您显示事件发生的顺序:

public class Main
{
    public static void main(String[] args)
    {
        final int value;

        value = score("ACGT", "AC");
        System.out.println(value);
    }

    public static int score(final String gene1,
                            final String gene2)
    {
        final char[] a;
        final char[] b;
        final int    s;

        a = gene1.toCharArray();
        b = gene2.toCharArray();
        s = score(a, b, 0, 0);

        return (s);
    }

    private static int score(final char[] a,
                             final char[] b,
                             final int    idxA,
                             final int    idxB)
    {
        final int value;

        // for all calls: a.length == 4 and b.length == 2
        // first call:  idxA == 0 and idxB == 0 - false || false == false
        // second call: idxA == 1 and idxB == 1 - false || false == false
        // third call:  idxA == 2 and idxB == 2 - false || true  == true      
        if(idxA >= a.length || idxB >= b.length)
        {
            // third call: will return 0            
            value = 0;
        }
        // first call:  a[idxA] == A and b[idxB] == A - true
        // second call: a[idxB] == C and b[idxB] == C - true 
        else if(a[idxA] == b[idxB])
        {
            // this is recursion
            // first call:  1 + score(a, b, 1, 1)
            // second call: 1 + score(a, b, 2, 2)

            // after the third call the call stack starts unwinding
            // second call: 1 + 0 == 1
            // first call:  1 + 1 == 2
            value = 1 + score(a, b, idxA + 1, idxB + 1);
        }
        else
        {
            final int x;
            final int y;

            x = score(a, b, idxA + 1, idxB);
            y = score(a, b, idxB,     idxB + 1);
            value = max(x, y);
        }

        // third call:  0
        // second call: 1
        // first call:  2
        return (value);
    }

    // Can you use Math.max(int, int) instad?
    private static int max(final int x, final int y)
    {
        final int value;

        if(x < y)
        {
            value = y;
        }
        else
        {
            value = x;
        }

        return (value);
    }
}
Run Code Online (Sandbox Code Playgroud)