我想了解回溯。 为此我开始使用以下链接 - 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;
}
答案 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);
}
}