题目 #
题目描述 #
给你一个序列X和另一个序列Z,当Z中的所有元素都在X中存在,并且在X中的下标顺序是严格递增的,那么就把Z叫做X的子序列。 例如:Z=是序列X=的一个子序列,Z中的元素在X中的下标序列为<1,2,4,6>。 现给你两个序列X和Y,请问它们的最长公共子序列的长度是多少?
输入描述 #
输入包含多组测试数据。每组输入占一行,为两个字符串,由若干个空格分隔。每个字符串的长度不超过100。
输出描述 #
对于每组输入,输出两个字符串的最长公共子序列的长度。
输入示例 #
abcfbc abfcab programming contest abcd mnp
输出示例 #
4 2 0
解答 #
1 动态规划求解 #
import java.io.*;
import java.util.*;
public class Main{
public static int getMax(String a,String b,int aLen,int bLen){
char[] aArr=a.toCharArray();
char[] bArr=b.toCharArray();
int[][] dp=new int[aLen+1][bLen+1];
for(int i=0;i<aLen+1;i++){
dp[i][0]=0;
}
for(int i=0;i<bLen+1;i++){
dp[0][i]=0;
}
for(int i=1;i<aLen+1;i++){
for(int j=1;j<bLen+1;j++){
int temp1=0;
if(aArr[i-1]==bArr[j-1]){
temp1=dp[i-1][j-1]+1;
}
dp[i][j]=Math.max(Math.max(dp[i-1][j],dp[i][j-1]),temp1);
}
}
return dp[aLen][bLen];
}
public static void main(String[] args) throws IOException{
BufferedReader in=new BufferedReader(new InputStreamReader(System.in));
PrintWriter out=new PrintWriter(System.out);
String line;
while((line=in.readLine())!=null){
String[] arr=line.split(" ");
String a=arr[0];
String b=arr[1];
int aLen=a.length();
int bLen=b.length();
out.println(getMax(a,b,aLen,bLen));
}
out.flush();
}
}
使用动态规划进行求解
核心的问题在于状态转移方程的设计
对于两个字符串,其实比较的主要内容是dp[i][j]中i和j对应的字符是否相同
- 如果相同的话,其转移方程是
dp[i-1][j-1]+1 - 如果不相同,其只可能从两个方向转过来:
dp[i-1][j]转变dp[i][j-1]转变
实际上就是这三者进行比较,取最大值即可
复杂度 #
时间复杂度: O(n * m),其中 n 和 m 分别为 text1 和 text2 的长度 空间复杂度: O(n * m)