【项目实训日志二】Shortest Superstring最短超串问题
Shortest Superstring最短超串问题
本文章总结一下《Approximation Algorithm》一书中第七章Shortest Superstring的相关内容。
问题定义
Given a finite alphabet Σ, and a set of n strings, find a shortest string s that contains each si as a substringS = {s1s_1s1,…,sns_nsn} ⊆ Σ+
Σ是一个有穷字符集,比如26个小写字母,S是s1s_1s1,…,sns_nsn这n个字符串的集合()假定这些字符串中,每一个都不是另一个的子集。,这些字符串中的字符都取自字符集Σ,比如由小写字母构成的字符串,并且不能是空串。最短超串问题就是找到一个包含S中所有字符串的最小字符串。
定义overlap
定义s,t之间的overlap同时是s的后缀和t的前缀,即两者之间首尾最大重合(最长)。
例:overlap(aabbb,bbbcc)=bbb,|overlap(aabbb,bbbcc)|=3
贪心算法举例
首先是一个贪心算法:在集合S中找出首尾匹配最大的两个串,将他们重叠拼接成一个新串,再放回集合S。重复上述步骤直到集合中只剩下一个字符串,这个串就是一个超串,它包含所有的sis_isi作为子字符串。但是贪心算法不一定能找到最优解,它的近似比为2(这里它还没有证明为什么近似比是2,只是说一下)。我们看一个例子假设有三个串 S={abkab^kabk, bkcb^kcbkc,bk+1b^{k+1}bk+1}。基于贪心策略,无法决定先拼接哪两个串,于是选择前两个串,得到abkcab^kcabkc,最后再和第三串拼接,得到abkcbk+1ab^kcb^{k+1}abkcbk+1。而实际上最短串是abk+1cab^{k+1}cabk+1c,他们几乎相差两倍。
abkab^kabk abbbbbbbb(k个b)
bkcb^kcbkc bbbbbbbbc(k个b)
bk+1b^{k+1}bk+1 bbbbbbbbb(k个b加1个b)
A factor 4 algorithm一个近似比为4的算法
具体算法
1.构造S中对应字符串的前缀图.
2.找到这个前缀图中的最小权重cycle cover,C = {c1c_1c1 ,…,ckc_kck }
3.输出σ(c1c_1c1 ) ◦ … ◦ σ(ckc_kck ).
理解算法
我们先找到最优解的一个良好的下界,假设s1s_1s1,s2s_2s2,…,sns_nsn按出现在最短超串s中最左边的顺序编号。
此图在这个问题中非常重要,需要刻进DNA里
令overlap(sis_isi ,sjs_jsj )表示sis_isi和sjs_jsj之间的最大重叠,也就是说,sis_isi的最长后缀是sjs_jsj的最长前缀。同时,用 prefix(sis_isi ,sjs_jsj )表示 sis_isi 中与 sjs_jsj没有重叠的部分。假设没有sis_isi是另一个的子字符串,我们得到
OPT =|prefix(s1s_1s1 ,s2s_2s2 )| + |prefix(s2s_2s2 ,s3s_3s3 )| + … + |prefix(sns_nsn ,s1s_1s1 )|+|overlap(sns_nsn ,s1s_1s1)|.
现在定义一个prefix graph:
S的前缀图定义如下:
它是一个在顶点集{1,…,n}上的有向图,对于每一对顶点i,j,从i到j的边权重为|prefix(sis_isi ,sjs_jsj )|(包括自环边——一个顶点到这个顶点自身的边)。
显然,|prefix(s1s_1s1 ,s2s_2s2 )| + |prefix(s2s_2s2 ,s3s_3s3 )| + … + |prefix(sns_nsn ,s1s_1s1 )代表了从1 → 2 → … → n → 1的权重。 因此,由(7.1)可知,通过前缀图的旅行商旅行的最小耗费给出了OPT的下界(因为该路径加上|overlap(sns_nsn,s1s_1s1)才是OPT|)。但是这个下界不是很有用,因为我们不能有效地计算旅行商的最小耗费(旅行商问题是np-hard的)。
所以换一种思路,使用前缀图的 圈覆盖(cycle cover) 的最小权值进行下界选择(在此书定义中,一个圈覆盖是覆盖所有顶点的不相交的圈的集合)。因为1→2→…→n→1是一个cycle cover,由(7.1)可得cycle cover的最低权重就是OPT的下限。
与最小TSP不同,一个cycle cover的最小权重是多项式时间可计算的。对应于前缀图,构造二分图H。U = {u1u_1u1,…,unu_nun}和V ={v1v_1v1 ,…,vnv_nvn }是该二分图的两部分。对任意 i,j ∈ {1,…,n} ,添加权重为 |prefix(sis_isi ,sjs_jsj )|的边(uiu_iui ,vjv_jvj )。很容易看出前缀图的每个cycle cover在H中都对应一个权重相同的完美匹配,反之亦然。因此,寻找最小的权重的cycle cover就归约为在H中寻找最小权值完美匹配。
[匹配:在图论中,一个「匹配」(matching)是一个边的集合,其中任意两条边都没有公共顶点。
完美匹配:如果一个图的某个匹配中,所有的顶点都是匹配点,那么它就是一个完美匹配。显然,完美匹配一定是最大匹配(完美匹配的任何一个点都已经匹配,添加一条新的匹配边一定会与已有的匹配边冲突)。]
如果c=(i1i_1i1 → i2i_2i2 → …ili_lil → i1i_1i1 ) 是前缀图中的一个回路,令α( c ) = prefix(si1s_{i_1}si1 ,si2s_{i_2}si2) ◦ … ◦ prefix(sil−1s_{i_{l-1}}sil−1 ,sils_{i_l}sil) ◦ prefix(sils_{i_l}sil ,si1s_{i_1}si1 ),注意到si1s_{i_1}si1 ,si2s_{i_2}si2 ,…,sils_{i_l}sil这些字符串都是(α(c))∞(α(c))^∞(α(c))∞的子字符串。接下来,令σ( c ) = α( c ) ◦si1s_{i_1}si1。
这时σ( c )就是si1s_{i_1}si1 ,…,sils_{i_l}sil的超串。注意σ( c ),是以 si1s_{i_1}si1的开始和结束的。在上述构造中,我们以任意字符串si1s_{i_1}si1“打开”回路c,称字符串si1s_{i_1}si1为c的代表字符串。
证明近似比为4
引理7.2
如果S’⊆S中的每个字符串都是字符串t对应的 t∞t^∞t∞ 的子字符串,那么在前缀图中存在一个权重最多为|t|的回路,它覆盖了S’中的字符串所对应的所有顶点。
证明:对S’中的每个字符串,定位其在t∞t^∞t∞中第一次出现的位置。显然,所有这些起始点将是不同的(因为在S中没有字符串是另一个字符串的子字符串),并且将位于t的第一个副本中。考虑前缀图中按此顺序访问相应顶点的回路。很明显,这个回路的权重最多是|t|。
引理7.3
设c和c’是C中的两条回路,r,r’是这两条回路的代表字符串。那么|overlap(r,r ‘)| < wt(c ) + wt(c’).
【下面照搬作者的证明过程,我个人没有看懂这个证明】
证明:[反证法]假设|overlap(r,r’ )| ≥ wt( c)+wt(c’ ),用 α代表长度为wt( c)的overlap(r,r’)的前缀。
显然,overlap(r,r’)既是 α∞α^∞α∞的前缀也是 (α′)∞(α' )^∞(α′)∞的前缀。此外, α是(α′)∞(α' )^∞(α′)∞的前缀,α’是 α∞α^∞α∞的前缀。由于overlap(r,r’ ) ≥ |α| + |α’ |,可得α和α’可交换,即α ◦ α’ = α’ ◦ α。然而, α∞α^∞α∞ = (α′)∞(α' )^∞(α′)∞,这是因为对任意k>0,αkα_kαk ◦ (α′)k(α' )_k(α′)k = (α′)k(α' )_k(α′)k ◦αkα_kαk .
所以,对任意N > 0, α∞α^∞α∞ 的长度为N的前缀与 (α′)∞(α' )^∞(α′)∞的相同。
现在,根据引理7.2,在覆盖c和c’中的所有字符串的前缀图中存在一个权重最多为wt( c)的回路,这与C\mathcal{C}C是最小cycle cover的事实相矛盾。
定理7.4证明
令 wt(C\mathcal{C}C) =∑i=1k\sum_{i=1}^{k}∑i=1kwt(cic_ici ),该算法的输出长度为
∑i=1k\sum\limits_{i=1}^{k}i=1∑k |σ(cic_ici)|= ∑i=1k\sum\limits_{i=1}^{k}i=1∑k |σ(αiα_iαi)|+∑i=1k\sum\limits_{i=1}^{k}i=1∑k|rir_iri|=wt(C\mathcal{C}C) +∑i=1k\sum\limits_{i=1}^{k}i=1∑k|rir_iri|,
其中 rir_iri 表示回路C中的代表字符串。要证明此算法近似比为4,需要证明该算法的输出长度∑i=1k\sum\limits_{i=1}^{k}i=1∑k |σ(cic_ici)|≤4OPT。我们已经证明了wt(C\mathcal{C}C) ≤ OPT,接下来,我们只需要证明代表字符串的长度总和∑i=1k\sum\limits_{i=1}^{k}i=1∑k|rir_iri|最多为3·OPT。
假设r1r_1r1 ,…,rkr_krk是按照它们在S的最短超串中从左到右第一次出现的次序排序的,由引理7.3[|overlap(r,r ‘)| < wt(c ) + wt(c’)]我们得到OPT的下界:
OPT ≥∑i=1k\sum\limits_{i=1}^{k}i=1∑k|rir_iri|−∑i=1k−1\sum\limits_{i=1}^{k-1}i=1∑k−1|overlap(rir_iri ,ri+1r_{i+1}ri+1 )| ≥∑i=1k\sum\limits_{i=1}^{k}i=1∑k|rir_iri| − 2∑i=1k\sum\limits_{i=1}^{k}i=1∑kwt(cic_ici ).
先看右半部分∑i=1k\sum\limits_{i=1}^{k}i=1∑k|rir_iri|−∑i=1k−1\sum\limits_{i=1}^{k-1}i=1∑k−1|overlap(rir_iri ,ri+1r_{i+1}ri+1 )| ≥∑i=1k\sum\limits_{i=1}^{k}i=1∑k|rir_iri| − 2∑i=1k\sum\limits_{i=1}^{k}i=1∑kwt(cic_ici ).(这里的等号没想明白什么时候取到,暂时看成>号也可以,不会对最后的结果产生影响)
因为[|overlap(r,r ‘)| < wt(c ) + wt(c’)],
所以∑i=1k−1\sum\limits_{i=1}^{k-1}i=1∑k−1|overlap(rir_iri ,ri+1r_{i+1}ri+1 )|=|overlap(r1r_1r1 ,r2r_2r2 )|+|overlap(r2r_2r2 ,r3r_3r3 )|+|overlap(r3r_3r3 ,r4r_4r4 )|+……+|overlap(rk−1r_{k-1}rk−1 ,rkr_krk) |
<wt(c1)+wt(c2)+wt(c2)+wt(c3)+wt(c3)+wt(c4)+……+wt(ck-1)+wt(ck)=2∑i=1k\sum\limits_{i=1}^{k}i=1∑kwt(cic_ici )-wt(c1)-wt(ck)(展开求和)
也就是说∑i=1k−1\sum\limits_{i=1}^{k-1}i=1∑k−1|overlap(rir_iri ,ri+1r_{i+1}ri+1 )|<2∑i=1k\sum\limits_{i=1}^{k}i=1∑kwt(cic_ici )-(wt(c1)+wt(ck))
那么-∑i=1k−1\sum\limits_{i=1}^{k-1}i=1∑k−1|overlap(rir_iri ,ri+1r_{i+1}ri+1 )|>-2∑i=1k\sum\limits_{i=1}^{k}i=1∑kwt(cic_ici )+(wt(c1)+wt(ck))(两边同时加负号)
那么-∑i=1k−1\sum\limits_{i=1}^{k-1}i=1∑k−1|overlap(rir_iri ,ri+1r_{i+1}ri+1 )|>-2∑i=1k\sum\limits_{i=1}^{k}i=1∑kwt(cic_ici ),
就得到∑i=1k\sum\limits_{i=1}^{k}i=1∑k|rir_iri|−∑i=1k−1\sum\limits_{i=1}^{k-1}i=1∑k−1|overlap(rir_iri ,ri+1r_{i+1}ri+1 )| >∑i=1k\sum\limits_{i=1}^{k}i=1∑k|rir_iri| − 2∑i=1k\sum\limits_{i=1}^{k}i=1∑kwt(cic_ici ).
所以,
∑i=1k\sum\limits_{i=1}^{k}i=1∑k|rir_iri|≤OPT+2∑i=1k\sum\limits_{i=1}^{k}i=1∑kwt(cic_ici )≤3·OPT.
所以该算法的输出
∑i=1k\sum\limits_{i=1}^{k}i=1∑k |σ(cic_ici)|=wt(C\mathcal{C}C) +∑i=1k\sum\limits_{i=1}^{k}i=1∑k|rir_iri|≤OPT+3·OPT=4OPT
证毕。
把近似比优化至3
定义压缩
令X代表一个字符串的集合。用||X||来表示X中字符串的长度之和。让我们定义一个超串s所实现的压缩为输入字符串的长度总和与|s|之间的差,即||S||−|s|。显然,最短的超串可以实现最大的压缩。已知有几种算法至少可以达到最优压缩的一半。
具体算法
1.构造S中的字符串所对应的前缀图。
2.找到这个图中的最小cycle cover C= {c1c_1c1 ,…,ckc_kck }.
3.在 {σ(c1c_1c1),…,σ(ckc_kck)} 上使用超串的贪心算法,输出结果字符串为 τ\tauτ.令OPTσOPT_σOPTσ代表SσS_σSσ = {σ(c1c_1c1)…σ(ckc_kck)},中的字符串的最短超串的长度,同时令rir_iri作为cic_ici的代表字符串。
证明近似比为3
引理7.6
|τ\tauτ| ≤ OPTσOPT_σOPTσ+ wt(C\mathcal{C}C)
证明:
不失一般性地假设σ(c1c_1c1),…,σ(ckc_kck )按照这个顺序在SσS_σSσ的最短超串中出现。SσS_σSσ上可以达到的最大压缩为
∑i=1k−1\sum\limits_{i=1}^{k-1}i=1∑k−1|overlap(σ(cic_ici ),σ(ci+1c_{i+1}ci+1))|.
因为每个字符串都有rir_iri既作为前缀也作为后缀,由引理7.3可知
|overlap(σ(cic_ici ),σ(ci+1c_{i+1}ci+1))|≤ wt(cic_ici) + wt(ci+1c_{i+1}ci+1).
所以,SσS_σSσ上可以达到的最大压缩最多为 2·wt(C\mathcal{C}C) ,即
|| SσS_σSσ|| − OPTσOPT_σOPTσ ≤ 2 · wt(C\mathcal{C}C) .
这个由SσS_σSσ上的贪心算法达成的压缩至少是最优压缩的一半。所以,
||SσS_σSσ|| − | τ\tauτ| ≥1/2 (||SσS_σSσ || − OPTσOPT_σOPTσ ).
所以,
2(| τ\tauτ| − OPTσOPT_σOPTσ) ≤ ||SσS_σSσ|| −OPTσOPT_σOPTσ ≤ 2 · wt(C\mathcal{C}C) .
得证。
最后,我们在引理7.7中把OPTσOPT_σOPTσ和OPT联系起来。
引理7.7
OPTσOPT_σOPTσ ≤ OPT + wt(C\mathcal{C}C)
证明:
令OPTrOPT_rOPTr代表SrS_rSr = {r1r_1r1 ,…,rkr_krk }中字符串的最短超串的长度。关键要注意每个σ(cic_ici )都由rir_iri开始和结束。因此, SσS_σSσ上所能达到的最优压缩至少会和 SrS_rSr 上的一样大。
即|| SσS_σSσ || − OPTσOPT_σOPTσ ≥ || SrS_rSr || − OPTrOPT_rOPTr .
显然,|| SσS_σSσ|| = || SrS_rSr|| + wt(C\mathcal{C}C) .
所以,OPTσOPT_σOPTσ≤ OPTrOPT_rOPTr + wt(C\mathcal{C}C) .
这个引理要先注意到OPTrOPT_rOPTr ≤ OPT
结合上述两条引理我们得到定理7.8:算法7.5是最短超串问题的一个近似比为3的近似算法。
- 【项目实训日志四】BR-MTC问题概述及思路总结
- linux部署项目tomcat不生成log4j日志问题
- linux部署项目tomcat不生成log4j日志问题
- Eclipse中Maven运行项目时在Console中无日志出现的问题解决
- 苏嵌项目实训 学习日志1
- web项目Log4j日志输出路径配置问题
- 开发日志:项目没错,但不管怎么修改页面/Java内容,在Tomcat上部署的项目都没有更新的问题
- 苏嵌项目实训 学习日志4
- 实训项目日志(二)
- 简练网软考知识点整理-项目问题日志(Issue Log)
- 基于sentry的前端错误监控日志系统(部署sentry服务器/前端项目部署)-让前端最快的定位到生产问题
- 解决tomcat下面部署多个项目log4j的日志输出会集中输出到一个项目中的问题
- 关于在nginx负载均衡下,项目共用log4j配置导致的日志混乱问题
- 淘金客II项目问题日志(AngularJs+BootStrap+Api接口开发)
- 苏嵌项目实训 学习日志3
- SLF4J日志系统在项目导入时频现的问题
- web项目Log4j日志输出路径配置问题
- 实训项目日志(三)——场景与道具
- 智能wifi小车项目日志及重要问题描述解决
- 苏嵌项目实训 学习日志2