使用回溯理解LCS

时间:2014-08-17 17:23:29

标签: java algorithm backtracking

我想了解回溯。 为此我开始使用以下链接 - http://en.wikibooks.org/wiki/Algorithms/Backtracking

它解释了LCS。我理解动态编程解决方案会更快,但我一步一个脚印。他们提供的伪代码是对的吗? 为了这 :         String [] a = {""," great"," square"," has"," a" ,"相同"," no","角落"};         String [] b = {""," great"," image"," has"," no" ," a","相同","形式"};

它还打印" no"。

这是我的尝试,有人可以改进/纠正它。

public ArrayList<String> getLongestCommonSubsequence(String[] a , String[] b, ArrayList<String> output)
{
    if(a.length == 0 || b.length == 0)
        return output;

    if(a[0]==b[0])
    {   
        output.add(a[0]);
        getLongestCommonSubsequence(Arrays.copyOfRange(a, 1, a.length), Arrays.copyOfRange(b, 1, b.length), output);
    }
    else
    {
        ArrayList<String> discardA = getLongestCommonSubsequence(Arrays.copyOfRange(a, 1, a.length), b, new ArrayList<String>());
        ArrayList<String> discardB = getLongestCommonSubsequence(a, Arrays.copyOfRange(b, 1, b.length), new ArrayList<String>());

        if(discardA.size() > discardB.size())
            output = discardA;
        if(discardB.size() > discardA.size())
            output = discardB;
    }
    return output;
}

根据@David Eisenstat的建议更新了方法 - 问题1 - 它仍然打印出来&#34; no&#34; 问题2 - 它仍然提供冗余值。我认为这是使用回溯的副作用。

public ArrayList<String> getLongestCommonSubsequence(String[] a , String[] b, ArrayList<String> output)
{
    if(a.length == 0 || b.length == 0)
        return output;

    if(a[0].equals(b[0]))
    {   
        output.add(a[0]);
        getLongestCommonSubsequence(Arrays.copyOfRange(a, 1, a.length), Arrays.copyOfRange(b, 1, b.length), output);
    }
    else
    {
        ArrayList<String> discardA = getLongestCommonSubsequence(Arrays.copyOfRange(a, 1, a.length), b, output);
        ArrayList<String> discardB = getLongestCommonSubsequence(a, Arrays.copyOfRange(b, 1, b.length), output);

        if(discardA.size() > discardB.size())
            output.addAll(discardA);
        else if(discardB.size() > discardA.size())
            output.addAll(discardB);
    }
    return output;
}

1 个答案:

答案 0 :(得分:0)

您已经对变量及其值之间的区别产生了影响。 if语句的真正分支假定getLongestCommonSubsequence将其输出保留在作为参数传递的特定ArrayList中。另一方面,假分支分配两个新的ArrayList并将输出留在一个或另一个而不是请求的存储位置。而不是output = discardA;您需要执行output.addAll(discardA);,以便将项目复制到正确的列表(同样适用于discardB)。此外,第二个if应该有else,因此只执行一个addAll

此外,您应该使用a[0].equals(b[0])而不是a[0] == b[0],但只要您的测试字符串为interned,就不会导致错误。

编辑:这就是我的想法:

import java.util.*;

public class LCS {
    static void getLongestCommonSubsequence(String[] a, String[] b, List<String> output) {
        if (a.length == 0 || b.length == 0) {
        } else if (a[0].equals(b[0])) {
            output.add(a[0]);
            getLongestCommonSubsequence(Arrays.copyOfRange(a, 1, a.length), Arrays.copyOfRange(b, 1, b.length), output);
        } else {
            List<String> discardA = new ArrayList<String>();
            getLongestCommonSubsequence(Arrays.copyOfRange(a, 1, a.length), b, discardA);
            List<String> discardB = new ArrayList<String>();
            getLongestCommonSubsequence(a, Arrays.copyOfRange(b, 1, b.length), discardB);
            if (discardA.size() >= discardB.size()) {
                output.addAll(discardA);
            } else {
                output.addAll(discardB);
            }
        }
    }

    public static void main(String[] args) {
        String[] a = {"The", "great", "square", "has", "a", "same", "no", "corners"};
        String[] b = {"The", "great", "image", "has", "no", "a", "same", "form"};
        List<String> output = new ArrayList<String>();
        getLongestCommonSubsequence(a, b, output);
        System.out.println(output);
    }
}