求最长连续公共子序列(最长公共字串)+长度+输出字串
DP求解最长公共子串
前面提到了子串是一种特殊的子序列,因此同样可以用DP来解决。定义数组的存储含义对于后面推导转移方程显得尤为重要,糟糕的数组定义会导致异常繁杂的转移方程。考虑到子串的连续性,将二维数组c[i][j]用来记录具有这样特点的子串——结尾同时也为为串x1x2⋯xi与y1y2⋯yj的结尾——的长度。
得到转移方程:
最长公共子串的长度为 max(c[i,j]), i∈{1,⋯,m},j∈{1,⋯,n}。
原理参考——链接
import java.util.Scanner;
public class Main04_1 {
public static void main(String [] args){
Scanner sc = new Scanner(System.in);
String str1 = sc.nextLine();
String str2 = sc.nextLine();
char [] numsA = str1.toCharArray();
char [] numsB = str2.toCharArray();
int countinusLen = ContinusLCS(numsA,numsB);
System.out.println(countinusLen);
}
//最长公共字串,最长连续公共子序列+输出最长公共字串,通过endHere
public static int ContinusLCS(char [] arr1, char [] arr2){
int len1 = arr1.length;
int len2 = arr2.length;
int [][]dp = new int[len1+1][len2+1];
int maxlen = 0;
int endHere = 0;//最长公共字串的最后一个位置
for(int i = 0;i<=len1;i++){
dp[i][0] = 0;
}
for(int i = 0;i<=len2;i++){
dp[0][i] =0;
}
for(int i = 1;i<=len1;i++){
for(int j = 1;j<=len2;j++){
if(arr1[i-1] == arr2[j-1]){
dp[i][j] = dp[i-1][j-1]+1;
if(dp[i][j] > maxlen){
maxlen = dp[i][j];
endHere = i;
}
}
}
}
//输出最长公共字串,通过endHere
for(int i = endHere-maxlen;i<endHere;i++){
System.out.print(arr1[i]);
}
System.out.println();
return maxlen;
}
}
运行结果:
123abcd4567
qbe12345d6
123
3