For faster navigation, this Iframe is preloading the Wikiwand page for Burrows-Wheeler变换.

Burrows-Wheeler变换

本條目存在以下問題,請協助改善本條目或在討論頁針對議題發表看法。 此條目需要精通或熟悉相关主题的编者参与及协助编辑。 (2012年10月2日)請邀請適合的人士改善本条目。更多的細節與詳情請參见討論頁。 此條目需要擴充关于内容描述的内容。 (2012年10月2日)请協助改善这篇條目,更進一步的信息可能會在討論頁扩充请求中找到。请在擴充條目後將此模板移除。

Burrows–Wheeler Transform(简称BWT,也称作块排序压缩),是一个被应用在数据压缩技术(如bzip2)中的算法。该算法于1994年被Michael Burrows英语Michael BurrowsDavid Wheeler英语David Wheeler在位于加利福尼亚州帕洛阿尔托的DEC系统研究中心英语DEC Systems Research Center发明[1]。它的基础是之前Wheeler在1983年发明的一种没有公开的转换方法。

当一个字符串用该算法转换时,算法只改变这个字符串中字符的顺序而并不改变其字符。如果原字符串有几个出现多次的子串,那么转换过的字符串上就会有一些连续重复的字符,这对压缩是很有用的。该方法能使得基于处理字符串中连续重复字符的技术(如MTF变换游程编码)的编码更容易被压缩。

举个例子:

算法输入 SIX.MIXED.PIXIES.SIFT.SIXTY.PIXIE.DUST.BOXES
算法输出 TEXYDST.E.IXIXIXXSSMPPS.B..E.S.EUSFXDIIOIIIT

该算法的输出因为有更多的重复字符而更容易被压缩了。

Burrows–Wheeler变换过程

算法将输入字符串的所有循环字符串按照字典序排序,并以排序后字符串形成的矩阵的最后一列为其输出。

Burrows–Wheeler变换过程
输入 所有的循环字符串 将所有的字符串按照字典序排序 输出最后一列
banana
$ b a n a n a
a $ b a n a n
n a $ b a n a
a n a $ b a n
n a n a $ b a
a n a n a $ b
b a n a n a $
$ b a n a n a
a $ b a n a n
a n a $ b a n
a n a n a $ b
b a n a n a $
n a $ b a n a
n a n a $ b a
a n n b $ a a

Burrows–Wheeler变换的还原过程

  • 基于上述的BWT变换过程,以字符串“banana”为例,我们得到了变换结果“annb$aa”。其还原过程见以下过程:
  1. 1 基于原字符串矩阵的最后一列为“annb$aa”,我们进行该列进行排序,得到“$aaabnn”,并将其作为还原矩阵的第一列
Burrows–Wheeler 还原过程 1
输入 转移 排序 组合
- - - - - - a
- - - - - - n
- - - - - - n
- - - - - - b
- - - - - - $
- - - - - - a
- - - - - - a
a - - - - - -
n - - - - - -
n - - - - - -
b - - - - - -
$ - - - - - -
a - - - - - -
a - - - - - -
$ - - - - - -
a - - - - - -
a - - - - - -
a - - - - - -
b - - - - - -
n - - - - - -
n - - - - - -
$ - - - - - a
a - - - - - n
a - - - - - n
a - - - - - b
b - - - - - $
n - - - - - a
n - - - - - a
  1. 2 经过1.1的转移、排序和组合,我们得到了7对邻接字符串:<a$> <na> <na> <ba> <$b> <an> <an>,将这7对邻接字符串进行排序后,得到<$b> <a$> <an> <an> <ba> <na> <na>,由此,我们得到了还原矩阵的第二列“b$nnaaa”
Burrows–Wheeler 还原过程 2
输入 转移 排序 组合
$ - - - - - a
a - - - - - n
a - - - - - n
a - - - - - b
b - - - - - $
n - - - - - a
n - - - - - a
a $ - - - - -
n a - - - - -
n a - - - - -
b a - - - - -
$ b - - - - -
a n - - - - -
a n - - - - -
$ b - - - - -
a $ - - - - -
a n - - - - -
a n - - - - -
b a - - - - -
n a - - - - -
n a - - - - -
$ b - - - - a
a $ - - - - n
a n - - - - n
a n - - - - b
b a - - - - $
n a - - - - a
n a - - - - a
  1. 3 经过1.2的转移、排序和组合,我们得到了7对邻接字符串:<a$b> <na$> <nan> <ban> <$ba> <ana> <ana>,将这7对邻接字符串进行排序后,得到<$ba> <a$b> <ana> <ana> <ban> <na$> <nan>,由此,我们得到了还原矩阵的第三列“abaan$n”
Burrows–Wheeler 还原过程 3
输入 转移 排序 组合
$ b - - - - a
a $ - - - - n
a n - - - - n
a n - - - - b
b a - - - - $
n a - - - - a
n a - - - - a
a $ b - - - -
n a $ - - - -
n a n - - - -
b a n - - - -
$ b a - - - -
a n a - - - -
a n a - - - -
$ b a - - - -
a $ b - - - -
a n a - - - -
a n a - - - -
b a n - - - -
n a $ - - - -
n a n - - - -
$ b a - - - a
a $ b - - - n
a n a - - - n
a n a - - - b
b a n - - - $
n a $ - - - a
n a n - - - a
  1. 4 经过1.3的转移、排序和组合,我们得到了7对邻接字符串:<a$ba> <na$b> <nana> <bana> <$ban> <ana$> <anan>,将这7对邻接字符串进行排序后,得到<$ban> < a$ba > <ana$> < anan > < bana > < na$b > < nana >,由此,我们得到了还原矩阵的第四列“na$naba”
Burrows–Wheeler 还原过程 4
输入 转移 排序 组合
$ b a - - - a
a $ b - - - n
a n a - - - n
a n a - - - b
b a n - - - $
n a $ - - - a
n a n - - - a
a $ b a - - -
n a $ b - - -
n a n a - - -
b a n a - - -
$ b a n - - -
a n a $ - - -
a n a n - - -
$ b a n - - -
a $ b a - - -
a n a $ - - -
a n a n - - -
b a n a - - -
n a $ b - - -
n a n a - - -
$ b a n - - a
a $ b a - - n
a n a $ - - n
a n a n - - b
b a n a - - $
n a $ b - - a
n a n a - - a
  1. 5 经过1.4的转移、排序和组合,我们得到了7对邻接字符串:<a$ban> <na$ba> <nana$> <banan> <$bana> <ana$b> <anana>,将这7对邻接字符串进行排序后,得到<$bana> <a$ban> < ana$b > <anana> <banan> <na$ba> <nana$>,由此,我们得到了还原矩阵的第五列“anbana$”
Burrows–Wheeler 还原过程 5
输入 转移 排序 组合
$ b a n - - a
a $ b a - - n
a n a $ - - n
a n a n - - b
b a n a - - $
n a $ b - - a
n a n a - - a
a $ b a n - -
n a $ b a - -
n a n a $ - -
b a n a n - -
$ b a n a - -
a n a $ b - -
a n a n a - -
$ b a n a - -
a $ b a n - -
a n a $ b - -
a n a n a - -
b a n a n - -
n a $ b a - -
n a n a $ - -
$ b a n a - a
a $ b a n - n
a n a $ b - n
a n a n a - b
b a n a n - $
n a $ b a - a
n a n a $ - a
  1. 6 经过1.5的转移、排序和组合,我们得到了7对邻接字符串:<a$bana> <na$ban> <nana$b> <banaan> <$banan> <ana$ba> <anana$>,将这7对邻接字符串进行排序后,得到<$banan> <a$bana> < ana$ba> <anana$> <banana> <na$ban> <nana$b>,由此,我们得到了还原矩阵的第六列“naa$anb”。
Burrows–Wheeler 还原过程 5
输入 转移 排序 组合
$ b a n a - a
a $ b a n - n
a n a $ b - n
a n a n a - b
b a n a n - $
n a $ b a - a
n a n a $ - a
a $ b a n a -
n a $ b a n -
n a n a $ b -
b a n a n a -
$ b a n a n -
a n a $ b a -
a n a n a $ -
$ b a n a n -
a $ b a n a -
a n a $ b a -
a n a n a $ -
b a n a n a -
n a $ b a n -
n a n a $ b -
$ b a n a n a
a $ b a n a n
a n a $ b a n
a n a n a $ b
b a n a n a $
n a $ b a n a
n a n a $ b a

经过六次排序转移与组合,还原出了原有的字符串即“$banana”。

python实现(基于next值方式)

def bwt(s):
    """对字符串进行Burrows-Wheeler变换 不使用唯一字符('EOF')做标记 返回索引值列表"""
    #创建所有循环字符串
    table = [s[i:] + s[:i] for i in range(len(s))]
    #获取排序后的结果
    table_sorted = table[:]
    table_sorted.sort()
    #获取已排序表每个字符串在未排序表中对应字符串的下一个字符串在已排序表中的索引值
    indexlist = []
    for t in table_sorted:
        index1 = table.index(t)
        index1 = index1+1 if index1 < len(s)-1 else 0
        index2 = table_sorted.index(table[index1])
        indexlist.append(index2)
    #取排序后结果的最后一列作为结果字符串
    r = ''.join([row[-1] for row in table_sorted])
    return r, indexlist

def ibwt(r,indexlist):
    """对字符串进行反Burrows-Wheeler变换 有索引值的反变换比使用唯一标记的反变换简单很多"""
    s=''
    x = indexlist[0]
    for _ in r:
        s = s + r[x]
        x = indexlist[x]
    return s

python实现(基于末尾添加唯一字符方式)

通过在末尾添加唯一字符(不与输入字串中任何字符相同)后再进行变换,可以不需要传递索引值列表,不过逆变换的时候要做更多计算。

下面的伪代码提供了一个逆过程的朴素实现(输入字符串s为原过程之输出):

 function inverseBWT(string s)   
   生成length(s)个空串
   repeat length(s) times
       将字符串s作为一列插入每个字符串的串首
       对所有字符串排序
   返回结尾为EOF的行
END = '\1'  #必须不与原字符串中任何字符相同

def bwt(s):
    """对字符串进行Burrows-Wheeler变换"""
    s = s + END
    #创建所有循环字符串
    table = [s[i:] + s[:i] for i in range(len(s))]
    #获取排序后的结果
    table_sorted = table[:]
    table_sorted.sort()
    #取排序后结果的最后一列作为结果字符串
    return ''.join([row[-1] for row in table_sorted])

def ibwt(r):
    table = [''] * len(r)
    for _ in r:
        table = sorted([r[m] + table[m] for m in range(len(r))])
    s = [row for row in table if row.endswith(END)][0]
    return s.rstrip(END)

参考资料

  1. ^ Compression comparison of BWT based file compressors页面存档备份,存于互联网档案馆)(英文)。

外部链接

{{bottomLinkPreText}} {{bottomLinkText}}
Burrows-Wheeler变换
Listen to this article

This browser is not supported by Wikiwand :(
Wikiwand requires a browser with modern capabilities in order to provide you with the best reading experience.
Please download and use one of the following browsers:

This article was just edited, click to reload
This article has been deleted on Wikipedia (Why?)

Back to homepage

Please click Add in the dialog above
Please click Allow in the top-left corner,
then click Install Now in the dialog
Please click Open in the download dialog,
then click Install
Please click the "Downloads" icon in the Safari toolbar, open the first download in the list,
then click Install
{{::$root.activation.text}}

Install Wikiwand

Install on Chrome Install on Firefox
Don't forget to rate us

Tell your friends about Wikiwand!

Gmail Facebook Twitter Link

Enjoying Wikiwand?

Tell your friends and spread the love:
Share on Gmail Share on Facebook Share on Twitter Share on Buffer

Our magic isn't perfect

You can help our automatic cover photo selection by reporting an unsuitable photo.

This photo is visually disturbing This photo is not a good choice

Thank you for helping!


Your input will affect cover photo selection, along with input from other users.

X

Get ready for Wikiwand 2.0 🎉! the new version arrives on September 1st! Don't want to wait?