美文网首页
LCS 问题求解

LCS 问题求解

作者: 奇点创客 | 来源:发表于2021-10-28 16:14 被阅读0次

LCS : longest common substring 即最长公共子串

LCS 问题就是求两个字符串最长公共子串的问题。
解法就是用一个矩阵来记录两个字符串中所有位置的两个字符之间的匹配情况,若是匹配则为1,否则为0。然后求出对角线最长的1序列,其对应的位置就是最长匹配子串的位置。

但是在0和1的矩阵中找最长的1对角线序列又要花去一定的时间。通过改进矩阵的生成方式和设置标记变量,可以省去这部分时间。

当字符匹配的时候,我们并不是简单的给相应元素赋上1,而是赋上其左上角元素的值加一。我们用两个标记变量来标记矩阵中值最大的元素的位置,在矩阵生成的过程中来判断当前生成的元素的值是不是最大的,据此来改变标记变量的值,那么到矩阵完成的时候,最长匹配子串的位置和长度就已经出来了。

算法的基本思想:
当字符匹配的时候,不是简单的给相应元素赋上1,而是赋上其左上角元素的值加一。
我们用两个标记变量来标记矩阵中值最大的元素的位置,在矩阵生成的过程中来判断
当前生成的元素的值是不是最大的,据此来改变标记变量的值,那么到矩阵完成的时
候,最长匹配子串的位置和长度就已经出来了。

C++ 实现

// std::format  为 C++20 特性
#include "stdc++.h"

using Table = std::vector<std::vector<int>>;

void print_table(const string& s1, const string& s2, const Table& t)
{
    cout << "  ";
    std::for_each(s1.cbegin(), s1.cend(), [](char ch){cout << format("{:>3}", ch);});
    cout << "\n";
    for (size_t i = 0; i < s2.size(); i++) {
        cout << format("{:>2}", s2[i]);
        for (size_t j = 0; j < s1.size(); j++)
            cout << format("{:>3}", t[i][j]);
        cout << "\n";
    }
}

string LCS(const string& s1, const string& s2)
{
    size_t s1_len = s1.size(), s2_len = s2.size();
    Table t(s2_len);
    std::for_each(t.begin(), t.end(), [s1_len](auto& v){ v.resize(s1_len); });

    size_t lcs_begin{}, lcs_end{}, lcs_len{};
    for (size_t i = 0; i < s2_len; i++) {
        for (size_t j =0; j < s1_len; j++) {
            if (s1[j] == s2[i]) t[i][j] = (i == 0 or j == 0) ? 1 :  t[i - 1][j - 1] + 1;  
            else t[i][j] = 0;
            if (lcs_len < t[i][j]) { lcs_len = t[i][j]; lcs_end = j; }
        }
    }
    print_table(s1, s2, t);
    lcs_begin = lcs_end - lcs_len + 1;

    return s1.substr(lcs_begin, lcs_len);
}

int main()
{
    string s1{"hello,world,123"};
    string s2{"HHHello,world,12345"};
    string lcs = LCS(s1, s2);
    cout << format("字符串: {} 和\n字符串: {} 的\n最长公共子串是:{}", s1, s2, lcs);
}

Python 实现:

# LCS : longest common substring 即最长公共子串

def print_table(s1, s2, t):
    print("-"*20)
    print("  ", end='')
    for i in range(len(s1)):
        print("{:>3}".format(s1[i]), end = '')
    print("")

    for i in range(len(s2)):
        print("{:>2}".format(s2[i]), end = '')
        for j in range(len(s1)):
            print("{:>3}".format(t[i][j]), end = '')
        print("")
 
def LCS(s1, s2):
    print("寻找 {} 和 {} 的最大公共子串".format(s1, s2))
    s1_len, s2_len = len(s1), len(s2)
    t = [[0 for _ in range(s1_len)] for _ in range(s2_len)]
    lcs_begin, lcs_end, lcs_len = 0, 0, 0

    for i in range(s2_len):
        for j in range(s1_len):
            if s1[j] == s2[i]:
                if i == 0 or j == 0: t[i][j] = 1
                else:                t[i][j] = t[i - 1][j - 1] + 1
            else:                    t[i][j] = 0

            if t[i][j] > lcs_len:
                lcs_len = t[i][j]; lcs_end = j

    print_table(s1, s2, t)
    lcs_begin = lcs_end - lcs_len + 1

    return s1[lcs_begin : lcs_end + 1]

if __name__ == '__main__':
    strs = ["hello", "hell", "Hello", "llo", "hello, world"]
    print("字符串列表:", strs)
    lcs = strs[0]
    for s in strs[1:]:
        lcs = LCS(lcs, s)
    
    print("字符串列表的最长公共子串是:{}".format(lcs))                         

相关文章

  • LCS 问题求解

    LCS : longest common substring 即最长公共子串 LCS 问题就是求两个字符串最长公共...

  • 动态规划(DP问题)

    目录 1. 概念2. 分治与动态规划3. 求解问题的特点4. 步骤5. 斐波那契数列6. 最长公共子序列(LCS)...

  • 最长单调递增子序列的三种解法

    找出由n个数组成的序列的最长单调递增子序列 原博客地址 解法一:转化成LCS问题求解,时间复杂度为O(n*n). ...

  • LCS问题

    LCS问题包括最长公共子序列和最长公共子串,其中,最长公共子串要求必须连续。 对于二者的求解方式 最长公共子序列:...

  • [LeetCode] 问题系列 - LCS: Longest C

    经典问题:LCS(最长公共字符长度) 问题给两个string A B,找这两个string里面的LCS: 最长公共...

  • 动态规划问题-LCS

    LCS 最长公共子序 如下 x 和 y 的最长公共子序长度为为 7 公式 实现 代码

  • 可计算问题笔记

    可计算问题理论笔记 计算机可以求解哪些问题? 求解计算问题的思路 衡量求解计算问题的算法优劣--复杂度分析 复杂度...

  • LCS (Lintcode 79 & Lintcode 77)

    总结两道LCS问题 (1). Longest Common Sub-sequence(Lintcode 77)(2...

  • 最长公共子序列

    最长公共子序列问题( Longest Common Subsequence problem,LCS) 是求两个给定...

  • lintcode 最长公共子序列

    给出两个字符串,找到最长公共子序列(LCS),返回LCS的长度。说明最长公共子序列的定义: 最长公共子序列问题是在...

网友评论

      本文标题:LCS 问题求解

      本文链接:https://www.haomeiwen.com/subject/zgyvaltx.html