您的位置:首页 > 其它

【项目实训日志二】Shortest Superstring最短超串问题

2020-07-14 06:30 225 查看

Shortest Superstring最短超串问题

  • A factor 4 algorithm一个近似比为4的算法
  • 把近似比优化至3

  • 本文章总结一下《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=1k​wt(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∑k​wt(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∑k​wt(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∑k​wt(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∑k​wt(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∑k​wt(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∑k​wt(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∑k​wt(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∑k​wt(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的近似算法。

    内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
    标签: