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); } } }