最长公共子串

5 篇文章 0 订阅

目录

题目:

输入描述:

输出描述:

示例1

输入

输出

备注:

思路分析-未空间压缩:

思路分析-空间压缩:

代码展示:


题目:

给定两个字符串str1和str2,输出两个字符串的最长公共子串,如果最长公共子串为空,输出-1。

输入描述:

输入包括两行,第一行代表字符串srr1,第二行代表字符串str2。 1 ≤ length( str1), length(str2) ≤ 5000

输出描述:

输出包括一行,代表最长公共子串。

示例1

输入

1AB2345CD 12345EF

输出

2345

备注:

时间复杂度O(N^2),额外空间复杂度O(1)。(n可以为其中任意一个字符串长度)

思路分析-未空间压缩:

  1. 申请一个二维表dp[s2.length()][s1.length()]
    1. 行代表str2,索引i代表字符串当前字符str2[i]
    2. 列代表str1,索引j代表字符串当前字符str1[j]
    3. dp[i][j]代表 以str2[i]结尾的字串str2` 与 以str1[j]结尾的字串str1` 的最长公共字串
      1. 因为str1与str2的最长公共字串一定会以某个i某个j结尾,所以dp[i][j]中的最大值就是公共字串的长度
      2. 然后将最大长度处的索引向前推,就可以得到最长公共字串
      3. 为什么会这样定义,因为子串要求要连续,所以当以i,j结尾且str2[i] == str1[j]时,如果上一个是连续,则当前也一定连续
  2. 初始化
    1. 首行如果相等,则dp[i][j] = 1 否则dp[i][j] = 0
    2. 不用初始化首列,因为dp只依赖于左上角
  3. 其余点:
    1. 如果str2[i] == str1[j]则dp[i][j] = dp[i-1][j-1] + 1
    2. 否则dp[i][j] = 0
    3. 在填写dp时,更新最大值max,与最大值对应的i的索引值pos
  4. 根据最大长度与索引值还原最长子串

思路分析-空间压缩:

  1. 因为dp只依赖于左上角,所以不需要再申请一个二维表
  2. 只需要几个变量,从右上角点开始,划“捺”
    1. 定义出发点,出发点一开始时(0,m-1)
    2. 出发点向左移动,遇到边界后向下移动

代码展示:

import java.io.*;

public class Main{
    public static void main(String[] args)throws IOException{
        BufferedReader read = new BufferedReader(new InputStreamReader(System.in));
        String s1 = read.readLine();
        String s2 = read.readLine();
        int n = s2.length();
        int m = s1.length();
        int col = m-1;//出发点的列
        int row = 0;//出发点的行
        int max=0;//最大长度
        int pos = -1;//索引
        while(col!=0 || row < n){
            int i = row;
            int j = col;
            int len = 0;
            while(i<n && j<m){//划“捺”
                if(s1.charAt(j) == s2.charAt(i)){
                    len++;
                    if(len>max){
                        max = len;
                        pos = i;
                    }
                    
                }else{
                    len=0;
                }
                i++;
                j++;
            }
            if(col == 0){//出发点先左移到边界,再下移
                row++;
            }else{
                col--;
            }
        }
        String str = s2.substring(pos-max+1,pos+1);
        if(str.length()==0){
            str = "-1";
        }
        System.out.println(str);
    }
}

  • 3
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值