求两个字符串的最长公共子串

题目:
查找两个字符串 s1,s2 中的最长公共子串 。

方法一:
嵌套循环,假设res为最终找到的子串。如果较长的字符串中包含较短的字符串的子串,且长度大于当前最大长度,则更新res 和 当前最大长度。
代码:

 public static void sameString(String s1,String s2){
     String max = s1.length () > s2.length () ? s1 : s2;
     String min = s1.length () > s2.length () ? s2 : s1;
     String res = "";
     int maxLength = -1;
     for(int i = 0;i < min.length ();i++){
        for(int j = i + 1;j <= min.length ();j++){
            if(max.contains (min.substring (i,j)) && j-i > maxLength){
                maxLength = j - i;
                res = min.substring (i,j);
            }
        }
    }
    if(maxLength == -1){
        System.out.println ("-1");
    }else{
        System.out.println (res);
    }
}

方法二:动态规划

  1. 创建大小为两个字符串长度的二维数组。
  2. 比较数组中每个点对应行列的字符是否相等,相等置1,不相等置0。dp[i][j] = 1
  3. 则数组中值为1的数字形成的各斜线就是相等的子串,斜线最长即子串最长。

进一步优化:

  1. 在计算某个二维数组的值的时候顺便计算出来当前最长的公共子串的长度。
  2. 即某个二维数组元素的值由 dp[i][j]=1演变为dp[i][j]=1 +dp[i-1][j-1]

代码:

public static String sameString(String s1,String s2) {
    String max = s1.length () > s2.length () ? s1 : s2;
    String min = s1.length () > s2.length () ? s2 : s1;
    int[][] dp = new int[min.length ()][max.length ()];
    int end_index = -1;
    int maxLength = -1;
    for (int i = 0; i < min.length (); i++) {
        for (int j = 0; j < max.length (); j++) {
            if (min.charAt (i) == max.charAt (j)) {
                if (i == 0 || j == 0) {
                    dp[i][j] = 1;
                } else {
                    dp[i][j] = 1 + dp[i - 1][j - 1];
                }
                if (dp[i][j] > maxLength) {
                    maxLength = dp[i][j];
                    end_index = j;
                }
            }
        }
    }
    for(int i = 0;i < s1.length ();i++){
        for(int j = 0;j < s2.length ();j++){
            System.out.print (dp[i][j] + " ");
        }
        System.out.println ();
    }
    end_index = end_index + 1;
    String res = max.substring (end_index - maxLength, end_index);
    return res;
}

你可能感兴趣的:(算法,动态规划)