1.最长公共子序列(不用连续)
这个方法是求长度的,返回值是int
class Solution {
public int longestCommonSubsequence(String str1, String str2) {
if(str1.length()==0||str2.length()==0)
return 0;
int rows=str1.length();
int colomns=str2.length();
int[][] dp=new int[rows][colomns];//dp[i][j]表示strs1[0...i]和str2[0...j]的最长公共子序列长度
//初始化dp[0][0]
if(str1.charAt(0)==str2.charAt(0))//当两个字符串的第一个字符相等那么就赋值为1,不等就0
dp[0][0]=1;
else
dp[0][0]=0;
for(int j=1;j<colomns;j++)//初始化第一行
dp[0][j]=Math.max(dp[0][j-1],str2.charAt(j)==str1.charAt(0)?1:0);
for(int i=1;i<rows;i++)//初始化第一列
dp[i][0]=Math.max(dp[i-1][0],str1.charAt(i)==str2.charAt(0)?1:0);
//接下来就是dp[i][j]的普通情况了
//看到下图的(L,L)位置,那么该位置可以从什么位置得到呢
//因为(L,L)位置是str1[1]=str2[1],所以可以从(A,A)位置得到,取(A,A)位置的值+1,即是子序列A和子序列A构成的最大公共子序列长度
for(int i=1;i<rows;i++){
for(int j=1;j<colomns;j++){
if(str1.charAt(i)==str2.charAt(j)){//依赖于左上角
dp[i][j]=dp[i-1][j-1]+1;
}
else{//依赖于正上方和左方的值
//是因为要找的是最长公共子序列,所以当两个不相同时,要保持前面所得出的结果,所以选两者较大的
dp[i][j]=Math.max(dp[i-1][j],dp[i][j-1]);
}//意义是:例如(L,C)这个位置他们对应的字符不相等所以只能去取前面一个状态的dp值
//【(L,L)意思是子序列AL和子序列AL构成的最大公共子序列长度】
//【(A,L)意思是子序列A和ALC构成的最大公共子序列长度】
}
}
return dp[rows-1][colomns-1];
}
}
//初始化第一行就是str1的第一个字符串与str2整串相比,所以最大公共子序列只能1,dp[0][j]为1的话那么dp[0][j+1]后面的都是1
//第一列也一个道理
// str2
// A L C H E M I S T
//str1 A 1 1 1 1 1 1 1 1 1
// L 1 2 2 2 2 2 2 2 2
// G 1
// O 1
//
// R 1
//
// I 1
//
// T 1
//
// H 1
//
// M 1
// S 1
这个方法是求最长子串的,返回值是String
public String lcse(String str1,String str2){
int rows=str1.length();
int coloums=str2.length();
if(rows==0||coloums==0)
return "";
int[][] dp=getdp(str1,str2);//根据上面求最大子序列长度的过程的dp数组
int i=rows-1;//作为str1的下标
int j=coloums-1;//作为str2的下标
char[] answer=new char[dp[i][j]];//长度为dp[i][j]的长度
int index=answer.length-1;//指向answer数组的下标,初始指向末端位置
while(index>=0){
if(j>0&&dp[i][j]==dp[i][j-1]){//想一想,此处的dp是怎么来的,我们可以再看看上面求最大长度的过程:
// 两个字符串对应的字符不相等时需要取舍正上方和正左方的dp值dp[i][j]=Math.max(dp[i-1][j],dp[i][j-1]);
j--;//往左移动
}
else if(i>0&&dp[i][j]==dp[i-1][j]){
i--;
}
else{//而这里:就是当前的dp值比它上方的和左方的dp值都要大,那意味着当前的dp值对应的字符一定是属于最长公共子序列里面的,是由它左上方的斜对角的dp值+1得来的
answer[index]=str1.charAt(i);
index--;
i--;
j--;
}
}
return String.valueOf(answer);
}
2.最长公共子串(需要连续)
这个方法是求长度的
public class Solution {//返回最大长度
public String LCS (String str1, String str2) {
int rows=str2.length();
int coloums=str1.length();
int[][] dp=new int[rows][coloums];
int answer=0;
for(int i=0;i<coloums;i++)//初始化第一行,
//遇到两个字符相关等就为1,不等就是0
dp[0][i]=(str2.charAt(0)==str1.charAt(i)?1:0);
for(int j=0;j<rows;j++)//初始化第一列
//跟初始化第一行的逻辑一样
dp[j][0]=(str1.charAt(0)==str2.charAt(j)?1:0);
for(int i=0;i<rows;i++){//状态转移递推
for(int j=0;j<coloums;j++){
if(str2.charAt(i)==str1.charAt(j))
dp[i][j]=dp[i-1][j-1]+1;
answer=Math.max(answer,dp[i][j]);
}
}
return answer;
}
}
这个是求对应的最长公共子串的
import java.util.*;
public class Solution {//返回对应子串
public String LCS (String str1, String str2) {
int rows=str2.length();
int coloums=str1.length();
int[][] dp=new int[rows][coloums];
int answer=0;//用于记录最长的子串长度
int lastIndex=0;//用于子串记录最长时str1的下标
for(int i=0;i<coloums;i++)//初始化第一行,
//遇到两个字符相关等就为1,不等就是0
dp[0][i]=(str2.charAt(0)==str1.charAt(i)?1:0);
for(int j=0;j<rows;j++)//初始化第一列
//跟初始化第一行的逻辑一样
dp[j][0]=(str1.charAt(0)==str2.charAt(j)?1:0);
int row=0;
int coloum=0;
for(row=1;row<rows;row++){//状态转移递推
for(coloum=1;coloum<coloums;coloum++){
if(str2.charAt(row)==str1.charAt(coloum)){
dp[row][coloum]=dp[row-1][coloum-1]+1;
if(answer<dp[row][coloum]){
answer=dp[row][coloum];
lastIndex=coloum;
}
}
}
}
return str1.substring(lastIndex-answer+1,lastIndex+1);
}
}
版权声明:本文为qq_45451226原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。