最长公共子序列问题
就是两个字符串求他们的最长公共子序列比如123 和231 最长公共子序列就是23,
就是用动态规划来实现,动态规划的一般逻辑,首先实现一个或者几个最简单的情况,然后再写出复杂情况到简单情况的转化关系,就可以得到结果了。
此题中简单情况就是两个字符串只有一个字符,然后直接判断他们是否相等,如果相等返回1,不等返回0,复杂情况比如12 和 1 ,可以转化成简单方法,
第一个字符串的第一个字符和第二个字符串的第一个字符比的结果加上第一个字符串的第二个字符 和空白比较,
第一个字符串的第一个字符和空白比加上 第一个字符串的第二个字符和第二个字符串的第一个字符。
比较结果取最大的作为最终结果
就可以得到一张矩阵图,而结果需要沿着矩阵图行走,行走规则就是从右下往左上走,如果数字有变化,则说明这个字符是在公共子序列中。
我犯了一个错误就是路线一定要按照先行后列 或者先列后行的顺序,不能一会行先一会列先,
生成结果二维数组的方法:
static int solve(char[] first, char[] second, int firstindex, int secondindex, Integer[][] result) {
if (firstindex < 0 || secondindex < 0) {
return 0;
}
if (result[firstindex][secondindex] != null) {
return result[firstindex][secondindex];
} else {
if (firstindex == secondindex && firstindex == 0) {
int num = first[firstindex] == second[secondindex] ? 1 : 0;
result[firstindex][secondindex] = num;
return num;
} else {
char firstchar = first[firstindex];
char secondchar = second[secondindex];
int left = 0;
int right = 0;
int both = 0;
left = solve(first, second, firstindex - 1, secondindex, result);
right = solve(first, second, firstindex, secondindex - 1, result);
both = solve(first, second, firstindex - 1, secondindex - 1, result) + (firstchar == secondchar ? 1 : 0);
result[firstindex][secondindex] = Math.max(Math.max(left, right), both);
return result[firstindex][secondindex];
}
}
}
生成最长公共子序列的方法(这个是抄的)
逻辑就是如果右下角的数据和上面的数据相等,就先向上移动,如果右下角和左边数据相等 再考虑向左边移动,其他情况就向左上移动,就是我刚刚说的必须要按照先行后列 或者先列后行的顺序
private static String lcse(Integer[][]arr,char[] first,char[] second){
char[]res=new char[arr[first.length-1][second.length-1]];
int m=first.length-1;
int n=second.length-1;
int index=res.length-1;
while(index>=0){
if(m>0 &&arr[m][n]==arr[m-1][n]){
m--;
}
else if(n>0&&arr[m][n]==arr[m][n-1]){
n--;
}else{
res[index--]=first[m];
m--;
n--;
}
}
return String.valueOf(res);
}