最长公共子串

给定两个字符串str1和str2,返回两个字符串的最长公共子串

解法一:动态规划

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
public int[][] getdp(char[] str1, char[] str2){
int[][] dp = nex int[str1.length][str2.length];
for (int i =0; i < str1.length; i++){
if (str1[i] == str2[0]){
dp[i][0] = 1;
}
}
for (int j =0; j < str2.length; j++){
if (str1[0] == str2[j]){
dp[0][j] = 1;
}
}
for (int i = 1; i < str1.length; i++){
for (int j = 1; j < str2.length; j++){
if(str1[i] == str2[j]){
dp[i][j] = dp[i-1][j-1] +1;
}
}
}
return dp;
}

public String lcst1(String str1, String str2){
if (str1 == null || str2 == null || str1 == "" || str2 == ""){
return "";
}
char[] chs1 = str1.toCharArray();
char[] chs2 = str2.tocharArray();

int[][] dp = getdp(chs1, chs2);

int end = 0;
int max = 0;

for (int i = 0; i< chs1.length; i++){
for (int j =0; j < chs2.length; j++){
if (dp[i][j] > max){
end = i;
max = dp[i][j];
}

}
}
return str1.substring(end-max+1, end+1);

}

解法二:从斜线最左上的位置想右下依次计算每个位置的值

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42

public String lcat2(String str1, String str2){
if (str1 == null || str2 == null || str1 == "" || str2 == ""){
return "";
}
char[] chs1 = str1.toCharArray();
char[] chs2 = str2.toCharArray();

int row = 0;
int col = chs2.length -1;
int max = 0;
int end = 0;

while(row < chs1.length){
int i = row;
int j = col;
int len = 0;
while (i < chs1.length && j < chs2.length){
if (chs1[i] != chs2[j]){
len = 0;
}else{
len++;
}

//记录最大值,以及结束字符的位置
if (len > max) {
end = i;
max = len;
}

i++;
j++;
}
if (col > 0){
col--;
}
else{
row++;
}
}
return str1.substring(end -max +1,end +1);
}