题目
给定两个字符串,计算出两个字符串中最长的公共子序列,要求顺序需要一致。
解题
使用动态规划从头到尾将结果累加到两个字符串最后的位置
private static int maxCommonSequance(String source1, String source2) {
int[][] result = new int[source1.length() + 1][source2.length() + 1];
for (int i = 1; i <= source1.length(); i++) {
for (int j = 1; j <= source2.length(); j++) {
if (source1.charAt(i - 1) == source2.charAt(j - 1)) {
//将前一个结果记在后面的位置上,可以减少对0位置的判断
result[i][j] = result[i - 1][j - 1] + 1;
} else {
//若当前位置不相同,则需要再i-1,j和i,j-1取最短
result[i][j] = Math.max(result[i - 1][j], result[i][j - 1]);
}
}
}
return result[source1.length()][source2.length()];
}
空间优化:
其实只取决于短的那个字符串在i位置的计数即可。这里需要考虑一个问题,因遍历顺序的问题,在短字符串i处原本短的被更新为长的结果,会导致最后的结果失真。解决办法就是先遍历短再遍历长的,即
for(int i=1;i<=longer;i++){
for(int j=1;j<=shorter;j++){
.....
}
}
优化后
private static int maxCommonSequance2(String longer, String shorter) {
int m = longer.length();
int n = shorter.length();
int[] result = new int[n + 1];
for (int i = 1; i <= m; i++) {
int[] tmpResult = new int[n + 1];
for (int j = 1; j <= n; j++) {
if (longer.charAt(i - 1) == shorter.charAt(j - 1)) {
tmpResult[j] = result[j - 1] + 1;
} else {
tmpResult[j] = Math.max(result[j], tmpResult[j - 1]);
}
}
result = tmpResult;
}
return result[n];
}