題目描述
計算兩個字符串的最大公共子串的長度,字符不區分大小寫
輸入描述
輸出描述
輸入兩個字符串
輸入例子
asdfas werasdfaswer
輸出例子
6
算法實現
import java.util.Arrays;
import java.util.Scanner;
/**
* All Rights Reserved !!!
*/
public class Main {
public static void main(String[] args) {
//Scanner scanner = new Scanner(System.in);
Scanner scanner = new Scanner(Main.class.getClassLoader().getResourceAsStream("data.txt"));
while (scanner.hasNext()) {
String n = scanner.next();
String m = scanner.next();
System.out.println(maxSubstringLength(n, m));
System.out.println(maxSubsequenceLength(n, m));
}
scanner.close();
}
private static int maxSubstringLength(String a, String b) {
int aLen = a.length() + 1;
int bLen = b.length() + 1;
int max = 0;
// 初始值默認爲0
int[][] f = new int[aLen][bLen];
for (int i = 1; i < aLen; i++) {
for (int j = 1; j < bLen; j++) {
if (a.charAt(i - 1) == b.charAt(j - 1)) {
f[i][j] = f[i - 1][j - 1] + 1;
} else {
f[i][j] = 0;
}
if (f[i][j] > max) {
max = f[i][j];
}
}
}
return max;
}
/**
* 動態規劃算法
* <pre>
* 事實上,最長公共子序列問題也有最優子結構性質。
* 記:
* Xi=﹤x1,⋯,xi﹥即X序列的前i個字符 (1≤i≤m)(前綴)
* 假定Z=﹤z1,⋯,zk﹥∈LCS(X , Y)。
*
* 若xm=yn(最後一個字符相同),則不難用反證法證實:該字符必是X與Y的任一最長公共子序列Z(設長度爲k)的最後一個字符,
* 即有zk = xm = yn 且顯然有Zk-1∈LCS(Xm-1 , Yn-1)即Z的前綴Zk-1是Xm-1與Yn-1的最長公共子序列。此時,問題化歸成
* 求Xm-1與Yn-1的LCS(LCS(X , Y)的長度等於LCS(Xm-1 , Yn-1)的長度加1)。
*
* 若xm≠yn,則亦不難用反證法證實:要麼Z∈LCS(Xm-1, Y),要麼Z∈LCS(X , Yn-1)。因爲zk≠xm與zk≠yn其中至少有一個必
* 成立,若zk≠xm則有Z∈LCS(Xm-1 , Y),相似的,若zk≠yn 則有Z∈LCS(X , Yn-1)。此時,問題化歸成求Xm-1與Y的LCS及
* X與Yn-1的LCS。LCS(X , Y)的長度爲:max{LCS(Xm-1 , Y)的長度, LCS(X , Yn-1)的長度}。
*
* 因爲上述當xm≠yn的狀況中,求LCS(Xm-1 , Y)的長度與LCS(X , Yn-1)的長度,這兩個問題不是相互獨立的:二者都須要求
* LCS(Xm-1,Yn-1)的長度。另外兩個序列的LCS中包含了兩個序列的前綴的LCS,故問題具備最優子結構性質考慮用動態規劃法。
* 也就是說,解決這個LCS問題,你要求三個方面的東西:
* 一、LCS(Xm-1,Yn-1)+1;
* 二、LCS(Xm-1,Y),LCS(X,Yn-1);
* 三、max{LCS(Xm-1,Y),LCS(X,Yn-1)}。
* 因此解決這個問題的動態轉移方程即:
* if xm==yn LCS(Xm,Yn)= LCS(Xm-1,Yn-1)+1;
* if xm!=yn LCS(Xm,Yn)= max{LCS(Xm-1,Yn),LCS(Xm,Yn-1)};
* </pre>
*
* @param a
* @param b
* @return
*/
private static int maxSubsequenceLength(String a, String b) {
int aLen = a.length() + 1;
int bLen = b.length() + 1;
// 初始值默認爲0
int[][] f = new int[aLen][bLen];
for (int i = 1; i < aLen; i++) {
for (int j = 1; j < bLen; j++) {
if (a.charAt(i - 1) == b.charAt(j - 1)) {
f[i][j] = f[i - 1][j - 1] + 1;
} else {
f[i][j] = Math.max(f[i - 1][j], f[i][j - 1]);
}
}
}
return f[aLen - 1][bLen - 1];
}
}