Java 使用回溯法理解LCS

Java 使用回溯法理解LCS,java,algorithm,backtracking,Java,Algorithm,Backtracking,我试图理解回溯。 为此,我从以下链接开始- 它解释了LCS。我知道动态规划解决方案会更快,但我正在一步一步走。他们提供的伪代码正确吗? 为此: 字符串[]a={“The”,“great”,“square”,“has”,“a”,“same”,“no”,“corners”}; 字符串[]b={“The”,“great”,“image”,“has”,“no”,“a”,“same”,“form”} 它还打印“否” 这是我的尝试,请有人改进/纠正一下 public ArrayList<String

我试图理解回溯。 为此,我从以下链接开始-

它解释了LCS。我知道动态规划解决方案会更快,但我正在一步一步走。他们提供的伪代码正确吗? 为此: 字符串[]a={“The”,“great”,“square”,“has”,“a”,“same”,“no”,“corners”}; 字符串[]b={“The”,“great”,“image”,“has”,“no”,“a”,“same”,“form”}

它还打印“否”

这是我的尝试,请有人改进/纠正一下

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;
}
公共ArrayList getLongestCommonSubsequence(字符串[]a,字符串[]b,ArrayList输出) { 如果(a.length==0 | | b.length==0) 返回输出; 如果(a[0]==b[0]) { 输出。添加(a[0]); getLongestCommonSubsequence(Arrays.copyOfRange(a,1,a.length),Arrays.copyOfRange(b,1,b.length),输出); } 其他的 { ArrayList discardA=getLongestCommonSubsequence(Arrays.copyOfRange(a,1,a.length),b,new ArrayList()); ArrayList discardB=getLongestCommonSubsequence(a,Arrays.copyOfRange(b,1,b.length),new ArrayList()); if(discardA.size()>discardB.size()) 输出=a; if(discardB.size()>discardA.size()) 输出=b; } 返回输出; } 更新了@David Eisenstat建议的方法- 问题1-它仍然打印“否” 问题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;
}
公共ArrayList getLongestCommonSubsequence(字符串[]a,字符串[]b,ArrayList输出) { 如果(a.length==0 | | b.length==0) 返回输出; 如果(a[0]。等于(b[0])) { 输出。添加(a[0]); getLongestCommonSubsequence(Arrays.copyOfRange(a,1,a.length),Arrays.copyOfRange(b,1,b.length),输出); } 其他的 { ArrayList discardA=getLongestCommonSubsequence(Arrays.copyOfRange(a,1,a.length),b,output); ArrayList discardB=getLongestCommonSubsequence(a,Arrays.copyOfRange(b,1,b.length),输出); if(discardA.size()>discardB.size()) output.addAll(discardA); else if(丢弃B.size()>丢弃A.size()) output.addAll(丢弃b); } 返回输出; }
您已经违反了变量及其值之间的区别。
if
语句的真正分支假定
getLongestCommonSubsequence
将其输出保留在作为参数传递的特定
ArrayList
中。另一方面,false分支分配两个新的
ArrayList
s,并将输出保留在其中一个位置,而不是请求的存储位置。而不是
output=discardA
您需要执行
output.addAll(discardA),以便将项目复制到正确的列表中(对于
discardB
,也是如此)。另外,第二个
if
应该有一个
else
,以便只执行一个
addAll

此外,您应该使用
a[0].equals(b[0])
而不是
a[0]==b[0]
,尽管只要测试字符串是正确的,这不会导致错误

编辑:以下是我的想法:

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);
    }
}
import java.util.*;
公共类LCS{
静态void getLongestCommonSubsequence(字符串[]a,字符串[]b,列表输出){
如果(a.length==0 | | b.length==0){
}else如果(a[0]。等于(b[0])){
输出。添加(a[0]);
getLongestCommonSubsequence(Arrays.copyOfRange(a,1,a.length),Arrays.copyOfRange(b,1,b.length),输出);
}否则{
List discardA=new ArrayList();
getLongestCommonSubsequence(Arrays.copyOfRange(a,1,a.length),b,a);
List discardB=新的ArrayList();
getLongestCommonSubsequence(a,Arrays.copyOfRange(b,1,b.length),discardB);
如果(discardA.size()>=discardB.size()){
output.addAll(discardA);
}否则{
output.addAll(丢弃b);
}
}
}
公共静态void main(字符串[]args){
字符串[]a={“The”,“great”,“square”,“has”,“a”,“same”,“no”,“corners”};
字符串[]b={“The”,“great”,“image”,“has”,“no”,“a”,“same”,“form”};
列表输出=新的ArrayList();
getLongestCommonSubsequence(a、b、输出);
系统输出打印项次(输出);
}
}

Hi@DavidEisenstat,谢谢回复。我用你的建议更新了原来的帖子。事实上,addAll是我之前做的,但它不起作用。因此,我删除了它以遵循伪代码中的建议。它仍然不起作用。有什么想法吗?@ND27您又做了一些我不想做的调整——仍然需要将递归调用运行到临时列表中。我把我版本的LCS代码粘贴到了我的答案中。有道理。谢谢:)