动态规划(带图)——查找两个字符串a,b中的最长公共子串

查找两个字符串a,b中的最长公共子串

题目

查找两个字符串str1,str2中的最长公共子串。若有多个,输出在较短串中最先出现的那个。

测试用例:

a b c d e f g h i j k l m n o p
a b c s a f j k l m n o p q r s t u v w

动态规划解法:

时间复杂度:O(n^m)
空间复杂度:O(n^2)

    public static String findMaxSubString(String str1,String str2) {
    	//最长字串开始位置
        int begin = 0;
        //长度
        int max = 0;
 		//因为要求是返回短串中较长的字串 所以我们这里默认str1是短串
        if(str1.length() > str2.length()) {
            String tmp = str1;
            str1 = str2;
            str2 = tmp;
        }
        int[][] dp = new int[str1.length()+1][str2.length()+1];
        //不用初始化  默认是 0
        // i 代表短字符串  j 代表长的字符串代表
        //dp[i][i] 中存放的内容代表的是当前有几个字符相等
        for(int i = 1;i < str1.length()+1;i++) {
            for(int j = 1;j < str2.length()+1;j++) {
                if (str1.charAt(i-1) == str2.charAt(j-1)) {
                //如果相等 dp[i-1][j-1] 表示上一个字符串是否相等
                    dp[i][j] = dp[i-1][j-1] + 1;
                }
                //因为最后是输出最长字符串 而不是输出最长字符串长度
                //所以要记录他的下标
                if(dp[i][j] > max) {     
                    begin = i;//记录字符串最长的末尾下标
                    max = dp[i][j];//记录字符串的长度
                }
            }
        }
        //打印dp数组
        for(int i = 0;i < str1.length();i++) {
            for (int j = 0; j < str2.length(); j++) {
                System.out.print(dp[i][j]+" ");
            }
            System.out.println();
        }
        return str1.substring(begin-max,begin);//begin-max代表的是起始下标
    }

对比下dp数组
在这里插入图片描述
正是我们想要的!

暴力查找

时间复杂度:0(n^2)
空间复杂度:0(1)

    public static String findMaxSubString1(String s1,String s2) {
    	//记录当前字串长度的
        int maxLen = 0;
        //保存当前字串的值
        String result = "";
        if(s1.length() > s2.length()) {
            String tmp = s1;
            s1 = s2;
            s2 = tmp;
        }
        for (int i = 0; i < s1.length(); i++) {
        	//注意 j <= s1.length();因为substring() 方法是左闭右开的
        	//牛客不取 = 也能过,但是你用它给题目的测试用例是过不了的,少了一个p
            for (int j = i+1; j <= s1.length(); j++) {
                if (s2.contains(s1.substring(i,j)) && s1.substring(i,j).length() > maxLen) {
                    result = s1.substring(i,j);
                    maxLen = s1.substring(i,j).length();
                }
            }
        }
        return result;
    }

端午节快乐啊!!!

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值