前言
由于原微软开源的基于古老的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: A Package for Automatic Evaluation of Summaries》