编写函数,获取两段字符串的最长公共子串的长度

本文介绍了如何使用动态规划解决最长公共子串问题,通过创建dp数组来存储子串长度,详细展示了getDp函数的实现步骤,并在find函数中调用该函数寻找最长子串。最后通过测试示例,展示整个过程的应用。

1.创建dp数组(算法核心是动态规划)

// 创建dp数组
    int[][] getDp(char[] arr1,char[] arr2){
        int[][] dp = new int[arr1.length][arr2.length];
        // 第一列赋值
        for (int i = 0; i < arr1.length; i++) {
            if (arr1[i] == arr2[0]){
                dp[i][0] = 1;
            }
        }

        // 第一行赋值
        for (int j = 1; j < arr2.length; j++) {
            if (arr2[j] == arr1[0]){
                dp[0][j] = 1;
            }
        }

        // 其余位置相等的赋值为 左上角加1 ==》当前子串长度
        for (int i = 1; i < arr1.length; i++) {
            for (int j = 1; j < arr2.length; j++) {
                if (arr1[i] == arr2[j]){
                    dp[i][j] = dp[i-1][j-1] + 1;
                }
            }
        }

        return dp;
    }

2.通过调用上面的getDp()方法,寻找最长公共子串的长度

// 寻找最长子串
    int find(String str1,String str2){
        // 判空
        if (str1 == null || str2 == null || str1.equals("") || str2.equals("")){
            return -1;
        }

        // 字符串转字符数组
        char[] arr1 = str1.toCharArray();
        char[] arr2 = str2.toCharArray();

        int[][] dp = getDp(arr1,arr2);

        int end = 0;
        int maxLength = 0;

        for (int i = 0; i < arr1.length; i++) {
            for (int j = 0; j < arr2.length; j++) {
                if (dp[i][j] > maxLength){
                    // end 即为结束子串的位置下标
                    end = i;
                    // 更新maxLength
                    maxLength = dp[i][j];
                }
            }
        }
        String subs = str1.substring(end-maxLength+1, end+1);
        System.out.println("两个字符串的最长相同子串:"+subs);

        return maxLength;
    }

3.测试运行

main()测试

Test test = new Test();
System.out.println(test.find("GCCCTAGCCAGDE", "GCGCCAGTGDE"));

输出:
在这里插入图片描述

转载地址:原文地址(有详解)

### 使用字符串哈希算法求解最长公共子串 #### 字符串哈希基础概念 字符串哈希是一种将字符串转换为整数值的技术,使得可以通过比较这些值来间接比较两个字符串是否相同。这种方法能够显著提高某些操作的速度,尤其是在处理大量字符串匹配问题时。 对于给定的两个字符串`str1`和`str2`,目标是在这两个字符串之间找到最长公共子串。为了利用字符串哈希解决这个问题,通常采用二分法配合滚动哈希技术来进行高效查询[^1]。 #### 实现思路 核心思想在于假设一个可能的最大长度`len`,验证是否存在这样的长度满足条件——即在这个长度下至少有一组相等的子串存在于两输入字符串之中。具体过程如下: - **初始化**:设定最小猜测长度`low=0`以及最高可能性`high=min(strlen(str1), strlen(str2))`。 - **循环判断**:当`low<=high`时执行以下逻辑: - 计算中间值`mid=(low+high)/2`; - 对于每一个起始位置,在两个字符串上计算长度为`mid`的所有子串对应的哈希值; - 如果发现有相同的哈希值,则说明找到了长度不小于`mid`的有效答案,更新当前最佳记录,设置新的搜索范围为更大的一半(`low=mid+1`);反之则缩小至更短的一半(`high=mid-1`); 最终得到的结果将是最后一次成功匹配到的长度及其对应的具体子串内容。 #### Python代码示例 下面给出一段基于上述原理编写的Python程序片段用于演示如何应用此方法解决问题: ```python def get_hash(s, p, m): """获取base-p模m下的字符串s的hash""" hash_value = 0 for c in s: hash_value = (hash_value * p + ord(c)) % m return hash_value def rabin_karp_search(text, pattern, base, mod): n, m = len(text), len(pattern) # Compute the hash value of text and pattern h_text = get_hash(text[:m], base, mod) h_pattern = get_hash(pattern, base, mod) power_of_base = pow(base, max(m-1, 0), mod) found_positions = [] if h_text == h_pattern: found_positions.append(0) for i in range(1, n-m+1): h_text = ((h_text - ord(text[i-1])*power_of_base)*base + ord(text[i+m-1]))%mod if h_text < 0: h_text += mod if h_text == h_pattern: found_positions.append(i) return found_positions def longest_common_substring_with_binary_search(s1, s2, base=257, mod=int(1e9)+7): low, high = 0, min(len(s1), len(s2)) best_len = 0 result = "" while low <= high: mid = (low + high)//2 seen_hashes_s1 = set() hashes_s1 = {} for start_pos in range(len(s1)-mid+1): substring = s1[start_pos:start_pos+mid] current_hash = get_hash(substring, base, mod) if current_hash not in hashes_s1: hashes_s1[current_hash] = [] hashes_s1[current_hash].append(start_pos) matches_found = False for start_pos in range(len(s2)-mid+1): substring = s2[start_pos:start_pos+mid] current_hash = get_hash(substring, base, mod) if current_hash in hashes_s1: positions_in_s1 = hashes_s1[current_hash] for pos in positions_in_s1: if s1[pos:pos+len(substring)] == substring: matches_found = True break if matches_found: break if matches_found: best_len = mid result = substring low = mid + 1 else: high = mid - 1 return {"length":best_len,"substring":result} ``` 该函数接受两个参数`s1`和`s2`作为要对比的目标字符串返回它们之间的最长公共子串的信息。这里采用了Rabin-Karp算法中的多项式滚动散列机制来加速子串哈希运算效率。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值