import java.util.*;
public class Solution {
/**
* 代码中的类名、方法名、参数名已经指定,请勿修改,直接返回方法规定的值即可
*
* longest common substring
* @param str1 string字符串 the string
* @param str2 string字符串 the string
* @return string字符串
*/
public String LCS (String str1, String str2) {
// 特殊情况
if (str1.length() == 0 || str2.length() == 0) {
return "-1";
}
int len1 = str1.length();
int len2 = str2.length();
// 子串要求连续,因此不能简单定义成“str1前i位与str2前j位组成的公共子串最大长度”这种无视连续关系的定义,找不到递推关系
// 因此,dp[i][j]表示以str1第i个字符和str2第j个字符结尾的最长公共子串长度
// 初始化-1
int[][] dp = new int[len1 + 1][len2 + 1];
// 不用递归尝试了,因为按照这个定义,当字符不相等时,直接赋0,无法进入递归分支
// 直接双重for循环搞定
// 只需要记录最大长度和str1结尾下标即可,start = end - maxLength
int maxLength = 0;
int end = 0;
for (int i = 1; i <= len1; i++) {
for (int j = 1; j <= len2; j++) {
if (str1.charAt(i - 1) == str2.charAt(j - 1)) {
// 公共字符,则根据定义,在dp[i-1][j-1]的基础上+1
dp[i][j] = dp[i - 1][j - 1] + 1;
} else {
dp[i][j] = 0;
}
// 更新最大值
if (dp[i][j] > maxLength) {
maxLength = dp[i][j];
// 注意!end配合substring使用,end是开区间,因此要记录实际下标的后一位,即i-1的后一位i
end = i;
}
}
}
// 截取str1子串并输出
if (maxLength == 0) {
// 不存在公共子串,返回"-1"
return String.valueOf(-1);
} else {
// 存在公共子串,返回最大子串
return str1.substring(end - maxLength, end);
}
}
}