zoukankan      html  css  js  c++  java
  • 最长公共子串的长度和构造

     最长公共子串是两个字符串都包含的一个字符串,需要连续。例如:

                          String s1 : abfc

                          String s2: abcd

    "abc"是他们的最长公共子序列,但是‘c’在s1中与”ab“不连续,因此”ab“是两个字符串的最长公共子串。

    简单总结下思路: 使用动态规划,用一个二维数组dp[i][j]表示 s1的1--i与s2的1--j的子串的最长公共子串。例如:dp[2][3] 表示s1的 ”ab“ 和s2的 ”abc“的最长公共子串。由子问题的结果逐步往上得到最终解。动态规划的最关键就是递推的定义最优解,最长公共子序列的递推公式为:

    dp[i][j] = dp[i-1][j-1] + 1        (ch1[i] == ch2[j])

    dp[i][j] = 0  (ch1[i] != ch2[j])

     (ch1[] ch2[] 分别为s1 s2转化来的字符数组)

      dp[i][j] = 0                    (i==0 || j == 0)

    由于需要连续的子串,因此一旦ch1[i] != ch2[j] 则讲dp[i][j] 置为0,所以还需要一个变量保存找到的所有子串中的最大长度为多少。代码如下:

    import java.util.*;
    public class LCS2 {
        public static void main (String [] args) {
            Scanner sc = new Scanner(System.in);
            while(sc.hasNext()) {       //输入两个字符串
                String s1 = sc.next();
                String s2 = sc.next();
                System.out.println("
    "+LCSLen(s1,s2));
            }
        }
    
        //最长公共子串的长度
        static int LCSLen(String s1,String s2) {
            char [] ch1 = s1.toCharArray();
            char [] ch2 = s2.toCharArray();
            int max = 0;      //记录当前最长公共子串的长度
            int end = 0;       //记录当前最长公共子串的末尾位置
            int [][] dp = new int[ch1.length+1][ch2.length+1];      //dp[i][j]表示ch1的0--i子串 与 ch2的0--j子串 的最长公共子串长度
            for(int i = 1; i <= ch1.length; i++) {
                for(int j = 1; j <= ch2.length; j++) {
                    if(ch1[i-1] == ch2[j-1]) {
                        dp[i][j] = dp[i-1][j-1] + 1;
                        if(dp[i][j] > max) {                  //找到了一个子串长度比之前的更长了,则更新到max
                            max = dp[i][j];
                            end = i;       //记录这个新子串在两个字符串中某个的末尾位置,这里记录子串的末尾所在s1位置(因为是把i赋给end了嘛)
                        }
                    }
                    else {
                        dp[i][j] = 0;         //有一个地方字符不等则需要从0开始重新计数,这也是与子序列的区别
                    }
                }
            }
            getLCS(s1,s1.length(),end,max);
            return  max;
        }
    
        //构造一个最长公共子串
        static void getLCS(String s1,int n,int end,int max) {
            StringBuffer sb = new StringBuffer();
            char[] ch = s1.toCharArray();
            
            //构造子串很简单,我们已经知道了子串在s1的末尾位置和子串长度,所以 (末尾-长度)---(末尾)即是子串
            for(int i = end-max; i<end; i++) {
                sb.append(ch[i]);
            }
            System.out.println(sb);
        }
    }
  • 相关阅读:
    Git_学习_01_ 常用 Git 命令清单
    Git_错误_03_ Git提交时显示用户 unknown
    Java微信小程序开发_00_资源帖
    Git_错误_02_error: src refspec master does not match any
    Java企业微信开发_08_素材管理之下载微信临时素材到本地服务器
    Java企业微信开发_07_JSSDK多图上传
    Java企业微信开发_07_总结一下企业微信的配置
    Java_数据交换_dom4j_01_解析xml
    Git_学习_00_资源帖
    小结:线段树 & 主席树 & 树状数组
  • 原文地址:https://www.cnblogs.com/shen-qian/p/11316901.html
Copyright © 2011-2022 走看看