時間複雜度為O(m*n)最長公共子串
阿新 • • 發佈:2019-02-05
什麼叫最長公共子串,就是兩個字串當中最長的連續的公共子串,注意連續;而子序列可以不連續,順序一樣即可,不要混淆。
對於兩個子串,我們先找出短字串L中(長的也可以)每個字元在長字串H中的位置,這樣我們就構建出一個二維表:
L:deasdfe1ra
H:unnasdsdfew333
這樣,我們只需要找到如圖所示類似的向量線就可以了,在構建這樣的二維表時,是按行的循序構建的,每當查詢到x==y時,就給此單元賦值:(x-1,y-1)+1
並同時記錄下最大值MAX和其座標;當表構建完時,只需要拿出最大值得座標,依次右上遍歷,就可以取得最長公共子串了;
這樣演算法的時間複雜度就為O(m*n);//兩子串長度乘積
好吧,我把這件的Java程式碼實現放下面,如果有更好的實現方案,歡迎分享出來,謝謝:
package temp; import java.util.ArrayList; import java.util.HashSet; /** * * @author SheyChen * */ public class Temp { /** * * @param l 短的字串(長的也行) * @param h 長字串 * @return 換回最長子串集合,考慮到有多個最大子串長度相等 */ public static HashSet<String> foo(String l, String h) { char[] cl = l.toCharArray(); char[] ch = h.toCharArray(); int[][] arry = new int[cl.length][ch.length]; int max = 0; /** * List中存放的Int陣列長度為2,第一位子串在是cl中最後一位元素所佔的下標,第二位是子串長度 */ ArrayList<int[]> val = new ArrayList<int[]>(); /** * 構建二維表 */ for (int i = 0; i < cl.length; i++) { for (int j = 0; j < ch.length; j++) { if (cl[i] == ch[j]) { if (i == 0 || j == 0) arry[i][j] = 1; else arry[i][j] = arry[i - 1][j - 1] + 1; if (arry[i][j] == max) { int[] temp = { i, max }; val.add(temp); } else if (arry[i][j] > max) { max = arry[i][j]; val.clear(); int[] temp = { i, max }; val.add(temp); } } else { arry[i][j] = 0; } } } HashSet<String> hs = new HashSet<String>(); if (val.isEmpty()) return hs; for (int[] in : val) { int index = in[0]; int len = in[1]; String s = ""; while (len-- > 0) { s = cl[index--] + s; } hs.add(s); } return hs; } public static void main(String[] args) { /** * 結果:sdfe */ String l = "deasdfe1ra"; String h = "unnasdsdfew333"; for (String s : foo(l, h)) { System.out.println(s); } System.out.println(); /** * 結果: * 123 * dde */ l = "123kdde123"; h = "123gddedde"; for (String s : foo(l, h)) { System.out.println(s); } } }