题目描述:
查找两个字符串a,b中的最长公共子串。若有多个,输出在较短串中最先出现的那个。
Java实现:
import java.util.Scanner;
public class Main {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
while (sc.hasNext()) {
String str1 = sc.nextLine();
String str2 = sc.nextLine();
if (str1.length() > str2.length()) {
System.out.println(getMaxComSubStr2(str2, str1));
} else {
System.out.println(getMaxComSubStr2(str1, str2));
}
}
}
//穷举法
private static String getMaxComSubStr(String str1, String str2) {
int maxLength = 0;
int start = 0;
int end = 0;
for (int i = 0; i < str1.length(); i++) {
for (int j = i+1; j <= str1.length(); j++) {
if (str2.contains(str1.substring(i, j)) && (j-i) > maxLength) {
maxLength = j - i;
start = i;
end = j;
}
}
}
return str1.substring(start, end);
}
//动态规划法
private static int[][] getdp(char[] chars1, char[] chars2) {
int[][] dp = new int[chars1.length][chars2.length];
//第一列
for (int i = 0; i < chars1.length; i++) {
if (chars1[i] == chars2[0])
dp[i][0] = 1;
}
//第一行
for (int j = 0; j < chars2.length; j++) {
if (chars1[0] == chars2[j])
dp[0][j] = 1;
}
for (int i = 1; i < chars1.length; i++) {
for (int j = 1; j < chars2.length; j++) {
if (chars1[i] == chars2[j]) {
dp[i][j] = dp[i-1][j-1] + 1;
}
}
}
return dp;
}
private static String getMaxComSubStr2(String str1, String str2) {
char[] chars1 = str1.toCharArray();
char[] chars2 = str2.toCharArray();
int[][] dp = getdp(chars1, chars2);
int end = 0;
int max = 0;
for (int i = 0; i < chars1.length; i++) {
for (int j = 0; j < chars2.length; j++) {
if (max < dp[i][j]) {
max = dp[i][j];
end = i;
}
}
}
return str1.substring(end+1-max, end+1);
}
}
关键点:
- 穷举法是遍历较短字符串的所有子串,判断较长字符串是否包含
- 动态规划法的关键是找出状态转移方程