我真的被一个问题困住了,给我一个字符串输入S,另一个字符串输入U代表整个子字符串和一个非负整数m。方法是lcs(S,U,m)
例如:设S=“aabacaab”,U=“aab”,m=2。然后我们有以下子串组合:
[a][ab]acaab
[a]abaca[ab]
a[a]baca[ab]
aab[a]ca[ab]
aabac[a][ab]
[aa][b]acaab
[aa]bacaa[b]
aabac[aa][b]
因此lcs(S, U, m)
返回8
,因为我们有8个不同的U子串组合,并且子串的m
个数受到限制
我最初的想法是将S
的第一个字符与U
的第一个字符进行比较,并通过缩短S
和U
来向下递归。但是,由于m
,我无法确定如何减少m
,因为缩短的S
和U
没有任何前一个状态的引用
在处理字符串上的动态编程时,“我的子问题应该是什么”的答案通常是前缀、后缀或子字符串
从你最后的笔记中,你已经正确地认识到我们可以通过解决后缀问题来解决原来的问题。我们还知道,我们的子问题必须知道剩下要使用的工件数量。此时,我们可以猜测子问题是什么,并尝试定义一个公式
我们可以让
f(i,j,k)
成为使用S
的最后i
个字母精确地k
子字符串来匹配U
的最后j
个字母的方法数。什么是边缘案例?如果j
和k
都是0,我们就没什么关系了;有一种方法可以什么都不做。如果i<j
我们无法匹配j
个字母,如果j<k
我们无法将j
个字母分割成足够的片段最后,您必须定义主递归。首先,我们可以跳过
S
的这个字母,它将f(i-1,j,k)
作为求和。现在,让Match-Length(i,j)
为S[-i:]
开头与U[-j:]
匹配的连续位置数。我们需要添加所有可能的匹配项:对于每个长度l
,1 <= l <= Match-Length(i,j)
,我们必须添加f(i-l, j-l, k-1)
。这包括所有情况编辑:用户qouify发布了一个更好的解决方案。此DP公式的直接翻译在时间
O(|S| |U|^2 m)
中运行,而他们的直接翻译在时间O(|S| |U| m)
中运行。可以修改我的公式以匹配该运行时,但您需要计算前缀和,以便在预处理和记忆后的f(i-l, j-l, k-1)
时间内可以找到O(1)
的每个和要缩短
m
,您必须查看S
中的当前字母 和U
。如果两个字母相同,则有两个(非 (排他性)情况:您当前正在匹配
S
的子字符串(这意味着使用 您已经打开了一个字符串,如[aa...
中的符号 哪种情况下可以继续匹配您仍然有严格正数量的子字符串要匹配 在哪种情况下,您可以开始新的匹配(无论您当前是什么) 是否匹配字符串)
为此,您将需要一个用于递归的附加参数 它指定当前是否匹配子字符串
指示已找到与问题匹配的基本情况 是当您到达
U
的末尾并且m
等于0
时以下是实现此解决方案的代码(请注意,该函数处理字母列表而不是字符串):
相关问题 更多 >
编程相关推荐