最长公共子串

本文详细介绍了最长公共子串的概念及其求解方法,并通过实例演示了如何使用动态规划解决该问题。同时对比了最长公共子串与最长公共子序列的区别。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

1、先科普下最长公共子序列 & 最长公共子串的区别:

找两个字符串的最长公共子串,这个子串要求在原字符串中是连续的。而最长公共子序列不要求连续

2、最长公共子串

 

 

其实这是一个序贯决策问题,可以用动态规划来求解。我们采用一个二维矩阵来记录中间的结果。这个二维矩阵怎么构造呢?直接举个例子吧:"bab"和"caba"(当然我们现在一眼就可以看出来最长公共子串是"ba"或"ab")

   b  a  b

c  0  0  0

a  0  1  0

b  1  0  1

a  0  1  0

我们看矩阵的斜对角线最长的那个就能找出最长公共子串。

不过在二维矩阵上找最长的由1组成的斜对角线也是件麻烦费时的事,下面改进:当要在矩阵是填1时让它等于其左上角元素加1。

   b  a  b

c  0  0  0

a  0  1  0

b  1  0  2

a  0  2  0

这样矩阵中的最大元素就是 最长公共子串的长度。

在构造这个二维矩阵的过程中由于得出矩阵的某一行后其上一行就没用了,所以实际上在程序中可以用一维数组来代替这个矩阵。

 

实现代码:

 

public class maxOfStr {

	public static void main(String[] args) {
		// TODO Auto-generated method stub
		String str1 = "mabcdf", str2 = "kfcdabck";
		char[] arr1 = str1.toCharArray();
		char[] arr2 = str2.toCharArray();
		int res[][] = new int[arr1.length+2][arr2.length+2];  //外面建一堵墙,全部为0,防止求左上角元素时数组越界
        int max=0;
		for (int i = 0; i < arr1.length; i++) {
			for (int j = 0; j < arr2.length; j++) {
                if (arr1[i]==arr2[j]) {
                	if (res[i][j]>0) {
                		res[i+1][j+1]=res[i][j]+1;
                		
					}else {
						res[i+1][j+1]=1;
					}
					max=Math.max(res[i+1][j+1], max);
				}
			}
		}
		
		System.out.println(max);

	}

}
public class LCS {

    public static void main(String[] args) {
        String a = "ddhehekabc";
        String b = "deekrtabc";
        fun(0, 0, a.toCharArray(), b.toCharArray());
        System.out.println(max);
    }

    static String max = "";
    static String temp = "";

    public static void fun(int startA, int startB, char[] a, char[] b) {
        if (startA == a.length || startB == b.length) return;

        for (int i = startA; i < a.length; i++) {
            for (int j = startB; j < b.length; j++) {
                if (a[i] == b[j]) {
                    temp = temp + a[i];
                    if (temp.length() > max.length()) {
                        max = temp;
                    }
                    fun(i + 1, j + 1, a, b);
                } else {
                    temp = "";
                }
            }
        }
    }
}

测试结果:

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值