160 likes | 340 Views
动态规划(八). 最长公共子串问题. [问题描述]一个字符串的某个子串,就是结定的字符串再去掉几个元素(可能一个也不去掉)。 形式化地,结定字符串 X=<Xl,X2,…,Xm>, 和另一字符串 Z=<Zl,Z2, … ,Zk>, 如果存在 X 的一个严格递增的下标序列< i1, i2, …, ik>, 使得对所有的 J = 1, 2, …, k , 有. 则 Z 是 X 的子串。例如 Z=<B, C, D, B> 就是 X=<A, B, C, B, D, A, B> 的一个子串, 相应的下标序列为<2,3,5,7>。
E N D
最长公共子串问题 [问题描述]一个字符串的某个子串,就是结定的字符串再去掉几个元素(可能一个也不去掉)。 形式化地,结定字符串X=<Xl,X2,…,Xm>,和另一字符串Z=<Zl,Z2,… ,Zk>,如果存在X的一个严格递增的下标序列<i1, i2, …, ik>,使得对所有的J = 1, 2, …, k ,有 则Z是X的子串。例如Z=<B, C, D, B> 就是X=<A, B, C, B, D, A, B>的一个子串, 相应的下标序列为<2,3,5,7>。 给定三个序列 X,Y和Z,如果Z既是X的一个子串又是Y的一个子串,则称Z是X和Y的公共子串。例如X=<A,B,C,B,D,A,D>,Y=<B,D,C,A,B,A>。 则序列<B,C,A>,即为X和Y的一个公共子串,但不是X和Y的最长公共子串(LCS), 因为还有比它更长的公共子串<B,C,B,A>。 <B,C,B,A>是X和Y的一个LCS ,字符串<B,D,A,B>也是。 [问题] 现输入两个字符串X=<X1, X2, …, Xm>和Y=<Y1, Y2, …, Yn>,要求出X和Y的最长公共子串。
分析 • 描述LCS问题最优解的结构 首先.我们给出一个字符串“前缀”的概念: 给定一个字符串X=<X1, X2, …, Xm>,对I= 0, 1, …, m,定义X的第i个前缀为 例如,如果X=<A,B,C,B,D,A,B>,则 而 则为空串。 两个输入字符串X和Y的所有前缀组成了LCS问题的子问题空间。由此我们发现LCS问题的最优子结构的三个性质: 设X=<X1, X2, …, Xm>和Y=<Y1, Y2, …, Yn>为两个输入字符串,并设X和Y的最长公共子串为Z=<Z1, Z2, …, Zk> 性质1:如果Xm = Yn,则Zk = Xm = Yn,且 也就是说,如果两个字符串最后一位字符相等,则它们的最长公共子串的最后一位就是这个字符,并且公共子串的第k-1个前缀是两个字符串前缀的最长公共子串
分析 • 举例说明: X = <A, B, E, …, G, F> Y= <C, D, H, …, K, F> 因X和Y的最后一位相等,则它们的最长公共子串Z的最后一位必为F,即有 Z = <……, F>的样式。并且 Z’=<……>是X’=<A, B, E, …,G> 和Y’=<C,D,H, …,K>的最长公共子串。 性质2: 也就是说,如果两个字符串最后一位不等,则它们的最长公共子串Z的最后一位不等于X的最后一位,就意味着Z是X的前缀与Y的最长公共子串。 举例说明: X = <A, B, E, …, G, M> Y= <C, D, H, …, K, S> Z= <……, F> 因X和Y最后一位不等,X和它的子串的最后一位也不等,则Z是X’=<A,B,E…,G>和Y的最长公共子串
分析-最优子结构 性质3: 也就是说,如果两个字符串最后一位不等,则它们的最长公共子串Z的最后一位不等于Y的最后一位,就意味着Z是X与Y的前缀的最长公共子串。 举例说明: X = <A, B, E, …, G, W> Y= <C, D, H, …, K, I> Z= <……, F> 因X和Y最后一位不等,Y和它的子串的最后一位也不等,则Z是X和Y’=<C,D,H, …K>的最长公共子串 由此可见,字符串X和Y的一个最长公共子串也是包含了两个字符串的前缀的一个最长公共子串,这就说明了LCS问题具备最优子结构性质。
递归地定义LCS的值 由LCS问题的最优子结构的三个性质可知,要求X=<X1, X2, …, Xm>和Y=<Y1, Y2, …, Yn> 的一个LCS,可能要检查如下子问题: 1.若Xm=Yn,我们就要找出 2.如果Xm≠Yn,我们就要解决两个问题: 取两者中较长者作为X和Y的LCS。由此我们很容易看出重叠子问题的性质:为找出X和Y的一个LCS,我们可能需要找X和 的一个LCS与 和Y的一个LCS,这两个子问题都包含着找 和 的LCS的子问题。还有许多其它子问题都具有公共子子问题。
递归地定义LCS的值 • 用实例来说明上述查找过程。 设X=<A,B,C,B>,Y=<B,D,C> 1) X4 = B, Y3=C , X4 <> Y3,因此转而求“ X’=<A,B,C>与Y的LCS” 和 “Y’= <B,D>与X的LCS”。谁长谁就是X和Y的LCS。 2a) X=<A,B,C>, Y=<B,D,C>, X3=Y3, 因此转而求X=<A,B>与Y=<B,D>的LCS。 2b) X=<A,B,C,B>, Y=<B,D>, X4<>Y2, 因此转而求X=<A,B,C>与Y=<B,D> 和 X=<A,B,C,B>与Y=<B>的LCS。 3a) X=<A,B>, Y= <B,D>, X2<>Y2, 因此转而求<A>与<B,D> 和<A,B>与<B>的LCS。 3b1)X=<A,B,C>, Y=<B,D>, X3<>Y2, 因此转而求<A,B,C>与<B>的LCS和<A,B>与<B,D>的LCS 3b2) X=<A,B,C,B>, Y=<B>, X4=Y1, 转而求 <A,B,C>与<>的LCS。在下一次计算中,就会遇到<A,B,C>与<>。显然,一个字符串与一个空串的公共子串仍是一个空串,长度为0。因此X=<A,B,C,B>, Y=<B>的LCS为<B>,长度为1 4a)同理, <A>与<B,D> 的LCS为<>; <A,B>与<B>的LCS为<B>, 因此<A,B>与<B,D>的LCS为<B> 4b)因<A,B,C>与<B>的LCS为<B>; <A,B>与<B,D>的LCS为<B> 故<A,B,C,B>与<B,D>的LCS为<B> 5a)因此<A,B>与<B,D>的LCS为<B> 故<A,B,C>与<B,D,C>的LCS为<B,C> 6) 因<A,B,C>与<B,D,C>的LCS为<B,C>; <A,B,C,B>与<B,D>的LCS为<B> 故 <A,B,C,B>与<B,D,C>的LCS为<B,C>
递归地定义LCS的值 设C[I,J]为字符串X和Y的最长公共子串的长度。X的长度为I,Y的长度为J。若I=0或者J=0,也就是说两个字符串之一的长度为0,当前LCS的长度值也必为0。由LCS问题的最优子结构可得递归式:
自底向上求LCS的值 • 我们看到C[I,J]由两个自变量构成,I表示X的长度,J表示Y的长度。那么选择哪一个作为阶段变量更好呢?由于两个字符串在性质上没有区别,因此选择哪一个作阶段变量都无所谓。为简单计,不妨取I作为阶段变量。 • 因此阶段变量k的值范围是:1<=k<=I. • 阶段k表示求X的第k个前缀X’k与Y的最长公共子串。
自底向上求LCS的值 • 状态数: 字符串Y有长度分别为1,2,…,J的前缀字符串。这些前缀字符串与字符串X’k可以产生多少种组合呢? 应该是J种,每种组合就会得到一个LCS,就是一个状态。 因此状态数为J。状态变量的取值范围为1<=m<=J
自底向上求LCS的值 • 决策数: • 根据前面讨论的LCS的三个性质,我们可以作如下的决策: if X[k] = Y[m] then C[k , m] := C[k-1, m-1] + 1 else begin if C[k-1, m] > C[k, m-1] then C[k, m] := C[k-1, m] else C[k, m] := C[k, m-1] end;
自底向上求LCS的值 • 初始阶段: • 长度为0的X前缀与Y的各种前缀的LCS为0,也就是C[0, m]:= 0 (1<=m<=J) • 长度为0的Y前缀与X的各种前缀的LCS为0,也就是C[k,0]:=0(1<=k<=I)
练习 • 完成求最长公共子串的完整程序。 • 测试数据:除前面一组数据外,用下面两组数据: 1) X=<1, 0, 0, 1, 0, 1, 0, 1>, Y=<0, 1, 0, 1, 1, 0, 1, 1, 0> 2)S1=ACCGGTCGAGTGCGCGGAAGCCGGCCGAA S2=GTTGTTCGGAATGCCGTTGCTCTGTAAA
进一步练习 • 如果有三个输入字符串要求最长公共子串,又该怎么做?王建德版竞赛指导的P333页有完整的讨论。在他的讨论中除再一次讲解了LCS的性质外,还讲到了当内存空间不够用时该怎么办的问题。非常重要,强烈推荐掌握。 • 进一步思考,如果有n个输入字符串要求最长公共子串,又该怎么做?你能分析出n个字符串的LCS的三条性质吗?
未讨论的动态规划类型 • 几何类型,代表题目有:凸多边形的三角形划分。 • 资源分配类型,如快餐问题 • 组合计数类型,如果陨石的秘密(NOI2001) 希望大家通过对已知类型试题的分析,真正掌握动态规划方法。
尚未深入学习的专题 • 字符串的应用问题,每年都有一道字符串方面的题目,故要引起高度重视。 • 搜索算法的深入 • 实数的应用问题 • 图和树的应用问题