//1.返回str1和str2的最长公共子序列
public int[][] getdp(char[] ch1, char[] ch2){
int[][] dp = new int[ch1.length][ch2.length];
dp[0][0] = ch1[0] == ch2[0] ? 1 : 0;
for(int i = 1; i < ch1.length; i++){
dp[i][0] = Math.max(dp[i-1][0], ch1[i] == ch2[0] ? 1 : 0);
}
for(int i = 1; i < ch2.length; i++){
dp[0][i] = Math.max(dp[0][i-1], ch1[0] == ch2[1] ? 1 : 0);
}
for(int i = 1; i < ch1.length; i++){
for(int j = 1; j < ch2.length; j++){
dp[i][j] = Math.max(dp[i-1][j], dp[i][j-1]);
if(ch1[i] == ch2[j]){
dp[i][j] = Math.max(dp[i][j], dp[i-1][j-1]+1);
}
}
}
return dp;
}
//反推回去,找出相同的字符
public String lcse(String str1, String str2){
if(str1 == null || str2 == null || str1.equals("") || str2.equals("")){
return "";
}
char[] ch1 = str1.toCharArray();
char[] ch2 = str2.toCharArray();
int[][] dp = getdp(ch1, ch2);
int n = ch1.length-1;
int m = ch2.length-1;
int[] res = new int[dp[n][m]];
int index = res.length-1;
while(index >= 0){
//说明dp[n][m]来源于dp[n-1][m]
if(n > 0 && dp[n][m] == dp[n-1][m]){
n--;
//说明dp[n][m]来源于dp[n][m-1]
} else if(m > 0 && dp[n][m] == dp[n][m-1]){
m--;
} else {
//说明dp[n][m]来源于dp[n-1][m-1]+1此时ch[n] == ch[m]
res[index--] = ch1[n];
n--;
m--;
}
}
return String.valueOf(res);
}
//2.进阶,返回两个字串的最长连续公共子串
//对于此问题与上述问题相似,只不过在对比每个ch[i] ch[j]的过程中,相等则说明该字符可以
//作为公共子串的最后一个字符,不相等则dp[i][j] = 0,以该字符开头的相等字符为0
public int[][] getdp2(char[] ch1, char[] ch2){
int[][] dp = new int[ch1.length][ch2.length];
dp[0][0] = ch1[0] == ch2[0] ? 1 : 0;
for(int i = 1; i < ch1.length; i++){
dp[i][0] = ch1[i] == ch2[0] ? 1 : 0;
}
for(int i = 1; i < ch2.length; i++){
dp[0][i] = ch1[0] == ch2[1] ? 1 : 0;
}
for(int i = 1; i < ch1.length; i++){
for(int j = 1; j < ch2.length; j++){
if(ch1[i] == ch2[j]){
dp[i][j] = dp[i-1][j-1] + 1;
}
}
}
return dp;
}
public String lcse2(String str1, String str2){
if(str1 == null || str2 == null || str1.equals("") || str2.equals("")){
return "";
}
char[] ch1 = str1.toCharArray();
char[] ch2 = str2.toCharArray();
int[][] dp = getdp2(ch1, ch2);
int end = 0;
int max = 0;
for(int i = 0; i < ch1.length; i++){
for(int j = 0; j < ch2.length; j++){
if(dp[i][j] > max){
end = i;
max = dp[i][j];
}
}
}
return str1.substring(end-max+1, end+1);
}
//以上可以把空间复杂度简化为o(1)
//因为每个i,j都需要的是i-1,j-1
//所以只需要记录每条斜线上的最大长度和最大长度处的index即可
//该解法是在上述dp中建立模型后的优化。
public String lcse3(String str1, String str2){
if(str1 == null || str2 == null || str1.equals("") || str2.equals("")){
return "";
}
char[] ch1 = str1.toCharArray();
char[] ch2 = str2.toCharArray();
int end = 0;
int max = 0;
int row = 0;
int col = ch2.length - 1;
while(row < ch1.length){
int i = row;
int j = col;
int len = 0;
while(i < ch1.length && j < ch2.length){
if(ch1[i] == ch2[j]){
len++;
} else {
len = 0;
}
if(len > max){
end = i;
max = len
}
i++;
j++
}
if(col > 0){
col--;
} else {
row++;
}
}
return str1.substring(end-max+1, end+1);
}
最长公共字符串问题
最新推荐文章于 2021-04-03 11:13:53 发布