import java.util.ArrayList;import java.util.Arrays;import java.util.Collection;import java.util.HashSet;import java.util.List;/** * LCS(Longest Common Subsequence)求最長公用字串系列 * * @author zzf * */public class LCS {private final static String[] empty = new String[0];/** * @return 最長公用字串(可能有多個長度相同的) */public static String[] lcs(String s1, String s2, boolean noRepeat) {//排除常用情況if (s1 == null || s1.length() == 0 || s2 == null || s2.length() == 0) {return empty;}int len1 = s1.length();int len2 = s2.length();if (len1==len2&&s1.equals(s2)) {return new String[] { s1 };}if (len1 > len2 && s1.indexOf(s2) != -1) {return new String[] { s2 };}if (len2 > len1 && s2.indexOf(s1) != -1) {return new String[] { s1 };}//構造對比矩陣char[] chs1 = s1.toCharArray();char[] chs2 = s2.toCharArray();boolean[][] as = new boolean[len1][len2];for (int i = 0; i < len1; i++) {char ch1 = chs1[i];for (int j = 0; j < len2; j++) {char ch2 = chs2[j];as[i][j] = ch1 == ch2;}}// 收集正向\對角線int max = 0;Collection<String> buf = noRepeat ? (new HashSet<String>()): (new ArrayList<String>());for (int i = 0; i < len1; i++) {for (int j = 0; j < len2; j++) {int len = lcsLength(i, j, len1, len2, as);if (len > 0 && len >= max) {max = len;buf.add(s1.substring(i, i + len));}}}// 取最長對角線(最長相符字元)List<String> ret = new ArrayList<String>();for (String s : buf) {if (s.length() == max) {ret.add(s);}}return ret.toArray(empty);}/** * 遞迴計算長度(對角線) */private static int lcsLength(int i, int j, int len1, int len2,boolean[][] as) {if (as[i][j]) {int c = 1;i++;j++;if (i < len1 && j < len2) {c += lcsLength(i, j, len1, len2, as);}return c;}return 0;}public static void main(String[] args) {{String s1 = "12345";String s2 = "12456";// 輸出[45,12]System.out.println(Arrays.asList(lcs(s1, s2, true)));}{String s1 = "123456";String s2 = "1205678";// 輸出[56,12]System.out.println(Arrays.asList(lcs(s1, s2, true)));}}}