問題:有兩個字符串str1和str2,求出兩個字符串中最長公共字符串。
例如:“acbbsdef”和"abbsced"的最長公共字符串是“bbs”
算法思路:
1、把兩個字符串分別以行和列組成一個二維矩陣。
2、比較二維矩陣中行和列對應的每個點的字符是否相同,是設置這個點為1,否設置這個點為0。
3、通過查找值為1的最長對角線來找到最長公共字符串。
通過上面str1和str2兩個字符串,分別得出以行和列組成的一個二維矩陣如下圖:
從上圖可以看到,str1和str2共有3個公共子串"bbs",公共子串長度為3。
為了避免后續查找對角線長度的操作:
可以先計算二維矩陣值的時候順便計算出來當前最長的公共子串的長度;
即:某個二維矩陣元素的值由item[i][j]=1演變為item[i][j]=1 +item[i-1][j-1]。
下面是代碼實現
public class MaxStringDemo { public static void main(String[] args) { String aa = "abc123edf"; String bb = "bc123jg"; maxUtil2(aa, bb); System.out.println(maxUtil2(aa, bb)); } public static StringBuilder maxUtil2(String str1, String str2) { //把字符串轉成字符數組 char[] arr1 = str1.toCharArray(); char[] arr2 = str2.toCharArray(); // 把兩個字符串分別以行和列組成一個二維矩陣 int[][] temp = new int[arr1.length][arr2.length]; // 存儲最長公共子串長度 int length = 0; //start表明最長公共子串的起始點,end表明最長公共子串的終止點 int end = 0; int start = 0; ////初始化二維矩陣中的第一行 for (int i = 0; i < arr2.length; i++) { temp[0][i] = (arr1[0] == arr2[i]) ? 1 : 0; } //初始化二維矩陣中的第一列 for (int j = 0; j < arr1.length; j++) { temp[j][0] = (arr2[0] == arr1[j]) ? 1 : 0; } //嵌套for循環:比較二維矩陣中每個點對應行列字符中否相等,相等的話值設置為1,否則設置為0 for (int i = 1; i < arr1.length; i++) { for (int j = 1; j < arr2.length; j++) { if (arr1[i] == arr2[j]) { temp[i][j] = temp[i - 1][j - 1] + 1; if (temp[i][j] > length) { length = temp[i][j]; end = j; } } else temp[i][j] = 0; } } //求出最長公共子串的起始點 start=end-length+1; StringBuilder sb=new StringBuilder(); //通過查找出值為1的最長對角線就能找到最長公共子串 for (int j = start; j < end+1; j++) { sb.append(arr2[j]); } return sb; } }
到這里,求出兩個字符串的最長公共字符串的問題已經解決!