• [Python]最长公共子序列 VS 最长公共子串[动态规划]


    前言

    由于原微软开源的基于古老的perl语言的Rouge依赖环境实在难以搭建,遂跟着Rouge论文的描述自行实现。
    Rouge存在N、L、S、W、SU等几大子评估指标。在复现Rouge-L的函数时,便遇到了本博文的问题:求两串的最长公共子序列。

    一 参考文献

    全文参考均如下博文。
    

    二 最长公共子序列 & 最长公共子串的区别

    1、最长公共子序列(Longest Common Subsequence,LCS):在字符串A和字符串B中都出现的序列,且顺序与母串保持一致最长的那个序列。
    2、最长公共子串(Longest Common Substring):相比LCS更加严格,序列必须连续出现,即公共的子字符串。

    eg: csdnblog与belong,最长公共子序列为blog,最长公共子串为lo。

    三 程序设计与实现

    3.1 最长公共子序列

    def longestCommonSubsequence(seqA, seqB):
        """
        最长公共子序列
        -----------
        [reference] 最长公共子序列与最长公共子串【动态规划】 https://blog.csdn.net/a515557595_xzb/article/details/88296989
        :param seqA:
        :param seqB:
        :return:
        """
        m = len(seqA);
        n = len(seqB);
        init_unit={
            "len":0,
            "lcs":[]
        }
        dp = [[ init_unit ]*(n+1) for i in range(m+1)]; # m+1行, n+1列
        for i in range(0, m+1):
            for j in range(0, n+1):
                if i==0 or j==0:
                    dp[i][j] = init_unit;
                elif seqA[i-1] == seqB[j-1]:
                    tmp_str = copy.copy((dp[i-1][j-1])["lcs"]);
                    tmp_str.append(seqA[i-1]);
                    unit = {
                        "len": (dp[i-1][j-1])["len"] + 1,
                        "lcs": tmp_str
                    }
                    dp[i][j] = unit;
                elif seqA[i-1] != seqB[j-1]:
                    if (dp[i-1][j])["len"] > (dp[i][j-1])["len"]: # 存储最长的信息
                        dp[i][j] = dp[i-1][j];
                    else:
                        dp[i][j] = dp[i][j-1];
                else:
                    pass;
                pass; # end inner for loop
            pass; # end outer for loop
        return dp[m][n];
    
    print( longestCommonSubsequence("GM%$ABG", "gbndGFMABG") ) # {'len': 5, 'lcs': ['G', 'M', 'A', 'B', 'G']}
    print( longestCommonSubsequence(["G", "M", "%", "$", "A", "B", "G"], ["g","b", "n", "d", "G", "F", "M", "A", "B","G"] ) ); # {'len': 5, 'lcs': ['G', 'M', 'A', 'B', 'G']}
    

    3.2 最长公共子串

    def longestCommonSubstring(strA, strB):
        """
        最长公共子串
        -----------
        [reference] 最长公共子序列与最长公共子串【动态规划】 https://blog.csdn.net/a515557595_xzb/article/details/88296989
        :param strA:
        :param strB:
        :return:
        """
        m = len(strA);
        n = len(strB);
        init_unit={
            "len":0,
            "lcs":[]
        }
        dp = [[ init_unit ]*(n+1) for i in range(m+1)]; # m+1行, n+1列
        result ={
            "len":0, # 记录最长公共子串的长度
            "lcs": []
        };
        for i in range(0, m+1): # 考虑i为0或j为0的情况
            for j in range(0, n+1):
                if i==0 or j==0 or ( strA[i-1] != strB[j-1] ):
                    dp[i][j] = init_unit;
                elif strA[i-1] == strB[j-1]:
                    tmp_str = copy.copy((dp[i-1][j-1])["lcs"]);
                    tmp_str.append(strA[i-1]);
                    unit = {
                        "len": (dp[i-1][j-1])["len"] + 1,
                        "lcs": tmp_str
                    }
                    dp[i][j] = unit;
    
                    if (dp[i][j])["len"] > result["len"]: # 存储最长的信息
                        result = copy.copy( dp[i][j] );
                else:
                    pass;
                pass; # end inner for loop
            pass; # end outer for loop
        return result;
    
    print( longestCommonSubstring("GM%$ABG", "gbndGFMABG") ) # {'len': 3, 'lcs': ['A', 'B', 'G']}
    print( longestCommonSubstring(["G", "M", "%", "$", "A", "B", "G"], ["g","b", "n", "d", "G", "F", "M", "A", "B","G"] ) ); # {'len': 3, 'lcs': ['A', 'B', 'G']}
    

    四 应用领域

    • 4.1 机器学习 > 自动文本摘要 / 机器翻译 / 机器阅读理解等任务中 > 评估指标 > Rouge-L
      • Rouge-L分类:
        • 句子级: 最长公共子序列
        • 文摘级: Union[多条句子] 最长公共子序列
      • 推荐博文: ROUGE评价方法详解(二)
      • 推荐论文: 《ROUGE: A Package for Automatic Evaluation of Summaries》
  • 相关阅读:
    教你怎样做个有“钱”途的測试project师
    使用具体解释及源代码解析Android中的Adapter、BaseAdapter、ArrayAdapter、SimpleAdapter和SimpleCursorAdapter
    html-上左右布局方式---ShinePans
    POJ1502 MPI Maelstrom Dijkstra
    Angry IP Scanner 获取设备的IP
    【Struts2学习笔记(12)】Struts2国际化
    使用SQL Profile及SQL Tuning Advisor固定运行计划
    sage开发url替换字符串
    柯塔娜大合唱,互联网安全观
    vim水平摆放全部窗体的三个方法
  • 原文地址:https://www.cnblogs.com/johnnyzen/p/11235417.html
Copyright © 2020-2023  润新知