动态规划解最长公共子串

来源 : 牛客题霸第127题
题目
给定两个字符串str1和str2,输出两个字符串的最长公共子串
题目保证str1和str2的最长公共子串存在且唯一。

示例1
str1 = “1AB2345CD”, str2 = “12345EF”
最长公共子串 “2345”

思路
用一维数组dp 保存str1某个元素在str2中已连续的个数
dp数组的长度比str2的长度大1
我们把str1的每个元素按序在str2中倒序比对,如果相等,则在dp对应的元素位的值设置为前一个元素位的值+1,表示已连续的个数。不相等,则设置为0,
同时需要记录str2中最大长度时的索引和最大长度值

str1 元素中1遍历后的
最大长度索引为0,最大长度为1
dp数组的值

str212345EF
dp01000000

str1 元素中A遍历后的
最大长度索引为0,最大长度为1
dp数组的值

str212345EF
dp00000000

str1 元素中B遍历后的
最大长度索引为0,最大长度为1
dp数组的值

str212345EF
dp00000000

str1 元素中2遍历后的
最大长度索引为1,最大长度为1
dp数组的值

str212345EF
dp00100000

str1 元素中3遍历后的
最大长度索引为2,最大长度为2
dp数组的值

str212345EF
dp00020000

str1 元素中4遍历后的
最大长度索引为3,最大长度为3
dp数组的值

str212345EF
dp00003000

str1 元素中5遍历后的
最大长度索引为4,最大长度为4
dp数组的值

str212345EF
dp00000400

str1 元素中C遍历后的
最大长度索引为4,最大长度为4
dp数组的值

str212345EF
dp00000000

str1 元素中D遍历后的
最大长度索引为4,最大长度为4
dp数组的值

str212345EF
dp00000000

最后截取str2 的最大长度索引往前推最大长度的字符串为最长公共子串

示例代码


    public static void main(String[] args) {
        String str1 ="asgsdfasd"; String str2 ="sdgsdfadsdAS";

        System.out.println(calc(str1,str2));
    }

    public static String calc(String str1, String str2) {
        int maxLenth = 0;
        //记录最长公共子串的长度
        //记录最长公共子串最后一个元素在字符串 str1中的位置
        int maxLastIndex = 0;
        int[] dp = new int[str2.length() + 1];
        for (int i = 0; i < str1.length(); i++) {
            //  注意这里是倒序
            for (int j = str2.length() - 1; j >= 0; j--) {
                //递推公式, 两个字符相等的情况
                if (str1.charAt(i) == str2.charAt(j)) {
                    dp[j + 1] = dp[j] + 1;

                    // 如果遇到了更长的子串,要更新,记录最长子串的长度,以及最长子串最后一个元素的位置
                    if (dp[j + 1] > maxLenth) {
                        maxLenth = dp[j + 1];
                        maxLastIndex = i;
                    }
                } else {
                    // 两个字符不相等则当前位置设为0
                    // 每次str1新元素开始在str2倒序比对时,dp数组的值是上个元素比较后的最新值
                    dp[j + 1] = 0;
                }
            }
        }

        // 最字符串进行截取, substring(a,b)  中 a  和  b 分别表示截取的开始和结束位置
        return str1.substring(maxLastIndex - maxLenth + 1, maxLastIndex + 1); 
    }

运行结果

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值