字符串系列3 最长公共子串

这里总结了几种常见的解决最长公共子串问题的方法。

方法1:暴力求解

最简单的方法当然是暴力啦,遍历一个字符串的所有子串,然后查看其它字符串是否都含有这个子串,从所有字符串都含有的子串中选一个最大的即可,这适合对时间要求不太紧的情况。

POJ 3080 AC代码:

public static void main(String[] args) {

    Scanner in = new Scanner(System.in);
    int cnt = Integer.valueOf(in.nextLine());
    while (cnt-- != 0) {
        int n = Integer.valueOf(in.nextLine());
        String[] strArr = new String[n];
        for (int i = 0; i < n; i++) {
            strArr[i] = in.nextLine();
        }
        
        String res = "";
        for (int i = 3; i <= 60; i++) {
            for (int j = 0; j <= i - 3; j++) {
                String tmp = strArr[0].substring(j, i);
                boolean flag = true;
                for (int k = 1; k < n; k++)
                    if (!strArr[k].contains(tmp)) {
                        flag = false;
                        break;
                    }
                if (flag && res.length() < tmp.length()) res = tmp;
                else if (flag && res.length() == tmp.length() && res.charAt(0) > tmp.charAt(0)) res = tmp;
            }
        }
        
        if (res.equals("")) System.out.println("no significant commonalities");
        else System.out.println(res);
    }
}

当然你可以使用 KMP 替换 contains 函数。

方法2 : 后缀数组

之前我已经总结了后缀数组相关知识点,如果不清楚的人可以直接阅读这篇博客:字符串系列4 后缀数组,我的博客是用python和C++实现,拿hiho 1403做验证的,然后这篇博客:最长公共子串问题的后缀数组解法,是POJ 3080的解答。

方法3:动态规划

对于最长公共子串问题,最常见的应该就是动态规划了,但是动态规划在处理两个以上的字符串的时候就显得捉襟见肘了,但是两个的话还是很好处理的。这种方法在参考1和参考3中写得很清楚了,我不废话了。

其它方法

见参考3。

参考

  1. 维基百科:Longest common substring problem
  2. leetcode(16):最长公共子串/最长公共子序列
  3. LeetCode718解答

你可能感兴趣的:(算法总结)