最长公共子串
-
需用动态规划求解,MCS[i][j]记录短字符串s1前i个字符和长字符串s2前j个字符的最长子串的长度,初始化所有值为0。
-
当s1[i-1] = s2[j-1]时,MCS[i][j] = MCS[i - 1][j - 1] +1,这里使用一个额外的值start来记录最长子串在短字符串s1中出现的起始位置,maxlen记录当前最长子串的长度,当MCS[i][j]<maxlen时,maxlen = MCS[i][j],则start = i - maxlen;当s1[i-1] !=s2[j-1]时不需要任何操作,最后获取substr(start, maxlen)即为所求。
import java.util.*;
public class Main{
public static void main(String[] args){
Scanner scanner = new Scanner(System.in);
while(scanner.hasNext()){
String s1 = scanner.nextLine();
String s2 = scanner.nextLine();
if(s1.length() < s2.length()){
System.out.println(getMaxSub(s1,s2));
}else{
System.out.println(getMaxSub(s2,s1));
}
}
}
public static String getMaxSub(String str1,String str2){
char[] ch1 = str1.toCharArray();
char[] ch2 = str2.toCharArray();
int l1 = ch1.length;
int l2 = ch2.length;
//最长字串的起始位置
int start = 0;
//最长公共子串的长度
int maxLen = 0;
//状态:以str1的第i个字符结尾和以str2的第j个字符结尾的最长公共子串的长度
int[][] maxSubLen = new int[l1+1][l2+1];
for(int i = 1;i <= l1;i++){
for(int j = 1;j <= l2;j++){
//如果第i个和第j个字符相等,就进行累加
if(ch1[i-1] == ch2[j-1]){
maxSubLen[i][j] = maxSubLen[i-1][j-1] + 1;
//更新
if(maxLen < maxSubLen[i][j]){
maxLen = maxSubLen[i][j];
start = i - maxLen;
}
}
}
}
return str1.substring(start,start + maxLen);
}
}