最长公共子串问题

题目:给定两个字符串 strl1,strl2, 返回两个字符串的最长公共子串的长度
例如: strl1 = "1AB234"  strl2 = "1234"  返回3

(牛客 HJ75公共子串计算)

这道题于左神书上的题, 有点不同(其实就是更简单了一点点),优化思路还是,参考的左神

题解:
1.硬解, 这里不做过多的描述
2.动态规划
3.更简单的升级一下2

那我们先看2.动态规划
首先,我们先看一个表格(二维数组)

我们先理解,这个表格(二维数组)干了什么?
--它用来比较字符 是否相同.
--在相同的时候, 去寻找它的前一个字符是否相同,或者说,直接在前一个字符比较的结果上+1 (不相同依旧是二维数组在i,j位置的 初始值0)
--反馈到代码就是:

if(strl1.charAt(i-1) == strl2.charAt(j-1)){
    num[i][j] = num[i-1][j-1]+1;
}


好, 那我们现在理解, 为什么要有这个表格(二维数组)?
--首先, 这道题, 目的: 最长的公共子串字符串长度,
所以, 我们可以 拆分成小问题, 将两个字符串, 拆分成单个字符, 去比较, 字符相等, 则在前一个匹配的结果上+1 ,(前一个字符 我们已经匹配完了, 按顺序从前往后匹配的)
--于是我们知道了这是动态规划, 利用子问题的结果完成下一个步骤.

那我们现在开始写代码:
--首先创建二维数组,长度strl1,strl2
--两层for循环,比较下标位置,字符是否相等,相等则为[i-1][j-1]+1

现在,出现了问题
如果看我的图,第一行或者第一列,能匹配上,依旧[i-1][j-1]+1
是不是会出现,数组下标越界问题?
所以,我们在设定数组长度的时候要 strl1+1,strl2+1
okk,到这里大致的思路就齐全了.


你可以先自我尝试写一下代码, 如果出现了问题,可以参考一下我的代码(已经跑过了)

public static void main(String[] args) {
        Scanner scanner = new Scanner(System.in);
        String strl1 = scanner.next();
        String strl2 = scanner.next();
        int max = 0;

        int[][] num = new int[strl1.length()+1][strl2.length()+1];

        for (int i = 1; i <= strl1.length(); i++) {
            for (int j = 1; j <= strl2.length(); j++) {
                if(strl1.charAt(i-1) == strl2.charAt(j-1)){
                    num[i][j] = num[i-1][j-1]+1;
                }
                if(max<num[i][j]){
                    max = num[i][j];
                }
            }
        }
        System.out.println(max);
    }

 

okk,现在这道题,你已经会了,但是上述方法,其实,有一些不必要的操作

所以,现在我们来看看怎么给他升级

 

还是这张图,
我画线来体现出,上述代码的流程:
你看,红线 就是for循环进行一个个字符的比较,
当比较到有绿色菱形的地方(字符相等),再寻找它的上一个[i-1][j-1],的位置, 也就是紫线操作
你有没有发现,
红色的操作就是冗余的
我们直接进行紫线操作
直接去比较,那紫线那条线不就行了?
也就是,我们只要按照顺序的,字符串的前一个字符结果
如下图操作

 那我们就按图写代码, 就大功告成了!!!!~~~~~


你们可以先自己尝试一下, 体验做出来的快乐, 但是我的代码还是po到下面啦, 有什么问题, 可以再跟着代码走一遍

public static void main(String[] args) {
        Scanner scanner = new Scanner(System.in);
        String s1 = scanner.nextLine();
        String s2 = scanner.nextLine();
        
        //也可以不转
        char[] a1 = s1.toCharArray();
        char[] a2 = s2.toCharArray();
        int row = 0;
        int col = a2.length-1;
        int max = 0;
        while (row<a1.length){
            int i = row;
            int j = col;
            int len = 0;
             while (i<a1.length && j<a2.length){
                if(a1[i]==a2[j]){
                    len++;
                } else{
                    len = 0;
                }
                if(max<len){
                    max = len;
                }
                i++;
                j++;
            }
            if(col>0){
                col--;
            } else {
                row++;
            }
            
        }
        System.out.println(max);
    }

 

 

 

  • 2
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值