求两个字符串的最大公共子串
思路一 暴力求解
没有实际写代码验证,只写一下我的思路。
- 比较得到较短的字符串str1
- 计算较短字符串的所有公共子串,存放在集合中
2.1 找子串的思路:两个循环,外层从0遍历到末尾,内层从当前的位置开始,逐个字符增加- 对集合中所有的子串按长度排序(需要自定义比较器,可能比较复杂)
- 从大的子串到小的子串循环,一次进行
str2.contains(子串i)
。
思路二 动态规划
- 构造一个大小为字符串长度的二维数组
- 二维数组的a[i][j]值为0或者1,如果是0,表示
str1[i] != str2[j]
,反之则是1
比如:abcde和ggbddgg的矩阵如下
0 0 0 0 0 0 0
0 0 1 0 0 0 0
0 0 0 1 0 0 0
0 0 0 0 1 0 0
0 0 0 0 0 0 0
3.
对角线最长的1序列
就是我们要求的最大长度为3
这种方式的难点在于如何求出对角线最长的1序列
思路二 改进
步骤2,我们可以计算出如果str1[i] == str2[j]
时,a[i][j] = a[i][j] + a[i-1][j-1]
得到的二维数组如下
0 0 0 0 0 0 0
0 0 1 0 0 0 0
0 0 0 2 0 0 0
0 0 0 0 3 0 0
0 0 0 0 0 0 0
矩阵中最大的值
就是最大公共子串
代码实现(java)
import java.util.Scanner;
public class Main {
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
while(scanner.hasNextLine()) {
char[] line1 = scanner.nextLine().toCharArray();
char[] line2 = scanner.nextLine().toCharArray();
int max = Integer.MIN_VALUE;
int[][] a = new int[line1.length][line2.length];
for (int i = 0; i < line1.length; i++) {
for (int j = 0; j < line2.length; j++) {
// 所有的值,得出是0还是1(是否相等)
a[i][j] = line1[i] == line2[j] ? 1 : 0;
// 非0行0列时,且相等时,加左上角的值
if (i != 0 && j != 0 && a[i][j] == 1) {
a[i][j] += a[i - 1][j - 1];
}
//System.out.print(a[i][j] + " ");
// 判断a[i][j]和现有最大长度,更新max
if (max < a[i][j]) {
max = a[i][j];
}
}
// System.out.println();
}
System.out.println(max);
}
}
}