最长公共子序列(longest common sequence)和最长公共子串(longest common substring)不一样。
子序列:公共序列 可以不相邻
公共子串:公共序列的字符必须连续。
公共子数组: 数组索引必须连续
方法一:
- 暴力法解题
* 即求出所有的子序列,找出最长的。
* 显然这是一个愚蠢的解法,竞赛必超时,面试必凉。
* 这里就不详述了。
方法二:
- 动态规划法
- 例如:求字符串Str1 = a b m n c , Str2 = a p b c q.
对于两个字符串的动态规划问题,套路是通用的,所以可以以模板的方法记下本类题目
构建DP table:
至此,我们可以求得最长公共子序列的长度,但是我们还要输出序列
在这里插入图片描述完整代码:
import java.util.Scanner;
public class Main{
public static void main(String[] args) {
Scanner in = new Scanner(System.in);
String str1 = in.nextLine();
String str2 = in.nextLine();
dp(str1, str2);
}
public static void dp(String str1,String str2) {
int len1 = str1.length();
int len2 = str2.length();
int[][] dpTable = new int[len1+1][len2+1];
//初始化第一列
int flag = 0;
for(int i=1;i<=len1;i++) {
if(flag == 1) {
dpTable[i][1] = 1;
}else if(str1.charAt(i-1)==str2.charAt(0) ) {
dpTable[i][1]=1;
flag = 1;
}else {
dpTable[i][1] = 0;
}
}
// 初始化第一行
flag = 0;
for(int j =1;j<=len2;j++) {
if(flag == 1) {
dpTable[1][j] = 1;
}else if(str2.charAt(j-1)==str1.charAt(0) ) {
dpTable[1][j]=1;
str.append(str2.charAt(j-1));
flag = 1;
}else {
dpTable[1][j] = 0;
}
}
for(int i=2;i<len1;i++) {
for(int j= 2;j<len2;j++) {
if(str1.charAt(i)==str2.charAt(j)&& !already) {
dpTable[i+1][j+1] = 1+ Math.max(dpTable[i][j],
Math.max(dpTable[i][j+1], dpTable[i+1][j]));
}else {
dpTable[i+1][j+1] = Math.max(dpTable[i][j+1], dpTable[i+1][j]);
}
}
}
System.out.println(dpTable[len1][len2]);
}
}
输出最长子序列,请看下文
有DP-table逆向推出序列