# 每日算法 -- 最长公共子串

package 牛客;

/**
* 最长公共子串
* 题目描述
* 给定两个字符串str1和str2,输出两个字符串的最长公共子串，如果最长公共子串为空，输出-1。
* 示例1:
* 输入 "1AB2345CD","12345EF"
* 返回值 "2345"
* 核心思路：（动态规划）
*
*/
public class NC127 {

/**
* 自己动态规划求解法超时
* 重复比较，耗时严重
*/
public static String LCS (String str1, String str2) {
//零界值判断
if (str1.isEmpty()||str2.isEmpty()) {
return "-1";
}

//定义一个数组确定哪些是比较过的
int len1 = str1.length(), len2 = str2.length();
int[][] dp = new int[len1][len2];

//找到相同字符
String result = "";
for (int i =0;i<str1.length();i++){
String temp = "";
for (int j =0;j<str2.length();j++){
if(dp[i][j]==0){
if(str1.charAt(i)==str2.charAt(j)){
//判断连续相等字符
String s1 = str1.substring(i,len1);
String s2 = str2.substring(j,len2);
if(!s1.isEmpty()&&!s2.isEmpty()){
temp = getMaxlen(s1,s2,dp,i,j);
}
}
if(temp.length()>result.length()){
result = temp;
temp = "";
}
}
if(str2.length()-j<result.length()){
break;
}
}
}
return result;
}
private static  String getMaxlen(String str1,String str2,int[][] dp,int indexi ,int indexj){
String result = "";
int len = str1.length()<str2.length()? str1.length():str2.length();
for (int i = 0;i<len;i++){
if(str1.charAt(i)!=str2.charAt(i)){
return result;
}else{
dp[indexi++][indexj++]+=1;
result+=str1.charAt(i);
}
}
return result;
}

/**
* 大神的动态规划
* @param str1
* @param str2
* @return
*/
public static String LCS2(String str1, String str2) {
if (str1.isEmpty()||str2.isEmpty()) {
return "-1";
}
int n1 = str1.length(), n2 = str2.length();
int[][] dp = new int[n1 + 1][n2 + 1];
int maxLen = 0;
int x = 0;
for (int i = 1; i <= n1; i++) {
char ch1 = str1.charAt(i - 1);
for (int j = 1; j <= n2; j++) {
char ch2 = str2.charAt(j - 1);
if (ch1 == ch2) {
dp[i][j] = dp[i - 1][j - 1] + 1;
if (dp[i][j] > maxLen) {
maxLen = dp[i][j];
x = i;
}
}
}
}
return maxLen == 0 ? "-1" : str1.substring(x - maxLen, x);
}

/**
* 滑动窗口算法
* @param str1 string字符串 the string
* @param str2 string字符串 the string
* @return string字符串
*/
public static String LCS1(String str1, String str2) {
// write code here
StringBuilder sb = new StringBuilder();
int start = 0, end = 1;
while (end < str1.length() + 1) {
if (str2.contains(str1.substring(start, end))) {
if (sb.length() < end - start) {
sb.delete(0, sb.length());
sb.append(str1, start, end);
}
} else {
start++;
}
end++;
}
if (sb.length() == 0) {
return "-1";
}
return sb.toString();
}

public static void main(String[] args) {
System.out.println(LCS("1AB2345CD","12345EF"));
System.out.println(LCS1("1AB2345CD","12345EF"));
}

}


03-28 2150
08-21 723