【问题标题】:Burrows-Wheeler Transform without EOF character没有 EOF 字符的 Burrows-Wheeler 变换
【发布时间】:2023-03-03 09:22:18
【问题描述】:

我需要在线性时间内执行著名的 Burrows-Wheeler 变换。我找到了一个带有后缀排序和 EOF 字符的解决方案,但是附加 EOF 会改变转换。例如:考虑字符串bcababa和两次旋转

  • s1 = abababc
  • s2 = ababcab

很明显 s1

  • s1 = ababa#bc
  • s2 = aba#bcab

现在 s2

【问题讨论】:

    标签: string algorithm sorting burrows-wheeler-transform


    【解决方案1】:

    您需要在字符串中包含 EOF 字符才能使 BWT 工作,否则您将无法执行逆变换来获取原始字符串。如果没有 EOF,字符串 "ba" 和 "ab" 具有相同的转换版本 ("ba")。使用 EOF,转换是不同的

    ab        ba
    
    a b |     a | b
    b | a     b a |
    | a b     | b a
    

    即ab 转换为“|ab”,ba 转换为“b|a”。

    BWT 需要 EOF,因为它标志着字符循环的开始点。

    回复:根据维基百科,在没有 EOF 字符的情况下进行操作,

    由于输入字符串的任何旋转都会导致相同的结果 转换后的字符串,BWT 不能在不添加“EOF”的情况下反转 标记输入,或者用信息增加输出,例如 作为索引,它可以识别输入字符串 其所有旋转的类。

    有一个变换的双射版本,通过它 转换后的字符串唯一地标识原始字符串。在这个版本中, 每个字符串都有一个相同长度的唯一倒数。

    双射变换是通过首先将输入分解为 Lyndon 词的非递增序列;存在这样的因式分解 由 Chen-Fox-Lyndon 定理,并且可以在线性时间内找到。 然后,算法将所有这些的所有旋转排序在一起 字;与通常的 Burrows-Wheeler 变换一样,这会产生 n 个字符串的排序序列。然后得到转换后的字符串 通过在此排序中选择每个字符串的最后一个字符 列表。

    【讨论】:

    • 我会解决 EOF 字符的问题。如果我有一个学生可以在没有 EOF 字符的情况下解决问题,因为“他/她只能找到没有它的解决方案”,我会让那个学生失败。
    • 检查是由自动系统执行的,如果我使用 EOF 我会得到一个“错误答案”。
    • 嗯很有趣 :) 那么你只需要在没有 EOF 的情况下执行它。不过,如果这是一个家庭作业/练习/面试问题,我对线性时间要求持怀疑态度,因为即使是简单的排序也不是线性时间操作。
    • @antti.huima 如果您使用与自身连接的字符串的后缀数组,您可以在线性时间和空间中进行操作。有关详细信息,请参阅我的答案。
    • 你不正确。 BWT 的实际实现不会在输出中明确包含哨兵。相反,原始字符串的索引与输出一起传递以进行解码(除非您使用双射版本,它速度较慢且鲜为人知)。因此,您可以对没有标记的输入进行逆变换,您只需要原始字符串索引。
    【解决方案2】:

    您可以通过计算与自身连接的字符串的后缀数组,在没有 EOF 字符的情况下在线性时间和空间中执行转换。然后遍历后缀数组。如果当前后缀数组值小于n,则将旋转的最后一个字符添加到输出数组中,该字符从后缀数组中当前值表示的位置开始。但是,这种方法会产生稍微不同的 BWT 转换结果,因为字符串旋转不会像 EOF 字符一样被排序。

    更详尽的描述可以在这里找到:http://www.quora.com/Algorithms/How-I-can-optimize-burrows-wheeler-transform-and-inverse-transform-to-work-in-O-n-time-O-n-space

    【讨论】:

    • 是否使用等同于与自身方法连接的字符串的 EOF 字符?我得到的输出似乎并不相同。使用 EOF 字符“\0”,它应该低于所有其他字符,我得到 ptr: 13, string: "CTAAAACACGAGA\0GATGCAGGTATTTTATGTTAGTGATGCATTTTATGGCTCCCCGAGCATATC" 使用连接输入法,我得到 ptr: 12, str: "TAAAACACGAGACGATGCGGATATTTTATGTTAGTGATGCATTTTATGGCTCCCCGAGCATATC" 即使我们忽略 NUL 终止符,输出仍然不同。
    • @DSnet 你使用了什么输入字符串? AGCTTTTCATTCTGACTGCAACGGGCAATATGTCTCTGTGTGGATTAAAAAAAGAGTCTCTGAC?
    • @DSnet... 好的,我可以重现您的结果。以后有时间我会调查的。谢谢!
    • 这是正确的字符串,感谢您这样做。我正在尝试使用 SAIS 编写 bzip2 编码器。目前,通过重复输入字符串技巧,我似乎能够生成有效的 bzip2 文件。但是,由于需要处理 2n 个实际输入而导致的减速是不幸的。
    • @DSnet 是的......我的方法肯定是错误的。问题是字符串旋转需要以 EOF 字符在字典上小于其他字符的方式进行排序。我没有 EOF 字符的方法在对后缀进行排序时没有考虑到这一点,因此排序顺序是错误的。这会导致它产生错误的输出。我已经更新了我的 Quora 答案。我想知道——如果你只是在写一个 bzip2 编码器,为什么你需要生成没有 EOF 字符的 BWT?为什么不直接采用我建议的第一种方法?
    【解决方案3】:

    我知道这个帖子已经很老了,但我遇到了同样的问题并想出了以下解决方案:

    • 找到字典顺序的最小字符串旋转并保存偏移量(需要反转)(我使用 lydon 分解)
    • 在旋转后的字符串上使用正常的 bwt 算法(这会产生正确的输出,因为所有算法都假定字符串后跟按字典顺序最小的字符)
    • 要反转:unbwt 使用例如从索引 0 开始向后搜索并将对应的字符写入保存的偏移量

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2011-08-20
      • 1970-01-01
      • 1970-01-01
      • 2013-06-20
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多