Python Burrows-Wheeler变换(BWT)重复字符串

Python Burrows-Wheeler变换(BWT)重复字符串,python,compression,burrows-wheeler-transform,inverse-transform,Python,Compression,Burrows Wheeler Transform,Inverse Transform,我正在用Python编写Burrows-Wheeler变换及其反变换。它适用于小弦,但当我测试大弦时,它就崩溃了。在某些点上,字符串似乎在循环。我确信这一定与解码器的最终循环有关,但我遵循不止一个网站上的步骤。我的执行情况如下: class BurrowsWheelerTransform: def __init__(self, data): self.data = data def transform(self): # get data siz

我正在用Python编写Burrows-Wheeler变换及其反变换。它适用于小弦,但当我测试大弦时,它就崩溃了。在某些点上,字符串似乎在循环。我确信这一定与解码器的最终循环有关,但我遵循不止一个网站上的步骤。我的执行情况如下:

class BurrowsWheelerTransform:

    def __init__(self, data):
        self.data = data

    def transform(self):
        # get data size
        size = len(self.data)
        # get order (by index) of rotations
        order = sorted(range(size), key=lambda i: self.data[i:])
        # get index of original rotation
        index = order.index(0)
        # return size appended with last column of (imaginary) rotation table
        return chr(255) * (index // 255) + chr(index % 255) + ''.join(self.data[(i - 1 + size) % size] for i in order)

    def restore(self):
        # get index of end of index
        eoi = next(i for i in range(len(self.data)) if ord(self.data[i]) < 255)
        # get index
        index = 255 * eoi + ord(self.data[eoi])
        # get tranformed content
        content = self.data[eoi + 1:]
        # get lshift array
        lshift = [i - 1 for symbol in sorted(set(content)) for i, x in enumerate(self.data) if x == symbol]
        # restore
        restored = ''
        for i in range(len(content)):
            index = lshift[index]
            restored += content[index]
        # return restored
        return restored
class BurrowsWheelerTransform:
定义初始化(自身,数据):
self.data=数据
def转换(自):
#获取数据大小
大小=长度(自身数据)
#获取旋转的顺序(通过索引)
顺序=排序(范围(大小),键=lambda i:self.data[i:])
#获取原始旋转的索引
索引=顺序。索引(0)
#返回大小随(假想的)旋转表的最后一列一起追加
返回chr(255)*(索引//255)+chr(索引%255)+''.join(按顺序为i的self.data[(i-1+size)%size]))
def恢复(自我):
#获取索引末尾的索引
如果ord(自数据[i])<255,则eoi=next(i表示范围内的i(len(自数据)))
#获取索引
索引=255*eoi+ord(自身数据[eoi])
#获取转换内容
content=self.data[eoi+1:]
#获取lshift数组
lshift=[i-1表示已排序(集合(内容))中的符号,i,x表示枚举(self.data)中的符号,如果x==symbol]
#恢复
还原=“”
对于范围内的i(len(content)):
索引=lshift[索引]
还原+=内容[索引]
#恢复原状
恢复原状
原始字符串:

罗斯特夫不愿打扰公主,也没有回去 但她仍留在村子里等待她离开。当她 马车驶出了房子,他骑上马车,陪着她走了八个小时 从Boguchrovo到我军占领的道路数英里。在 在扬科沃的旅馆里,他第一次恭敬地向她告别 时间允许他吻她的手

你怎么能这么说!他脸红地回答玛丽公主 表达对她获救的感激之情,正如她所说的那样 发生。任何警察都会做同样的事!如果我们有 只有农民去打仗,我们不应该让敌人走这么远, 他羞愧地说,想换个话题。我是 很高兴有机会认识你。 再见,公主。我祝你幸福、安慰,并希望 在更快乐的环境中再次见到你。如果你不想让我 脸红,请不要谢我

解码字符串:

罗斯特夫不愿打扰公主,也没有回去 但她仍留在村子里等待她离开。当她 马车驶出了房子,他骑上马车,陪着她走了八个小时 从Boguchrovo到我军占领的道路数英里。在 在扬科沃的旅馆里,他第一次恭敬地向她告别 时间允许他吻她的手

你怎么能这么说!不愿意打扰公主, 罗斯特夫没有回到房子里,而是留在了村子里 等待她的离去。当她的马车驶出房子时,他 从Boguchrovo骑上并陪伴她八英里到达 这条路被我们的部队占领了。在扬科沃酒店,他恭敬地说 向她告别,这是他第一次允许自己吻她 手

你怎么能这么说!不愿意打扰公主, 罗斯特夫没有回到房子里,而是留在了村子里 等待她的离去。什么时候


奇怪的是,我在web上找到并测试过的其他实现(如和)似乎也会出现这种情况。发生了什么事?我是否误解了转换的工作原理?或者这个实现是不正确的

找到了答案!该算法基于以下假设:字符串连接到最后一个字符,该字符是唯一的,并且在词典学上比字符串中的任何其他字符都小。但是,由于我打算对任何给定字符使用0-255范围内的任何值,因此我不需要额外的符号。幸运的是,经过一些额外的bug修复,我已经能够稍微修改我的初始实现来解释这个事实。这是:

class BurrowsWheelerTransform:

    def __init__(self, data):
        self.data = data

    def transform(self):
        # get data size
        size = len(self.data)
        # get doubled string
        self.data *= 2
        # get order (by index) of rotations
        order = sorted(range(size), key=lambda i: self.data[i:])
        # get index of original rotation
        index = order.index(0)
        # return index appended with last column of (imaginary) rotation table
        return chr(255) * (index // 255) + chr(index % 255) + ''.join(self.data[(i - 1 + size) % size] for i in order)

    def restore(self):
        # get index of end of index
        eoi = next(i for i in range(len(self.data)) if ord(self.data[i]) < 255)
        # get index
        index = 255 * eoi + ord(self.data[eoi])
        # get tranformed content
        content = self.data[eoi + 1:]
        size = len(content)
        # get lshift array
        lshift = [i for symbol in sorted(set(content)) for i, x in enumerate(content) if x == symbol]
        # restore
        restored = ''
        for i in range(size):
            index = lshift[index]
            if index >= size: break
            restored += content[index]
        # return restored
        return restored
class BurrowsWheelerTransform:
定义初始化(自身,数据):
self.data=数据
def转换(自):
#获取数据大小
大小=长度(自身数据)
#获得双倍的字符串
self.data*=2
#获取旋转的顺序(通过索引)
顺序=排序(范围(大小),键=lambda i:self.data[i:])
#获取原始旋转的索引
索引=顺序。索引(0)
#返回索引附加(虚拟)旋转表的最后一列
返回chr(255)*(索引//255)+chr(索引%255)+''.join(按顺序为i的self.data[(i-1+size)%size]))
def恢复(自我):
#获取索引末尾的索引
如果ord(自数据[i])<255,则eoi=next(i表示范围内的i(len(自数据)))
#获取索引
索引=255*eoi+ord(自身数据[eoi])
#获取转换内容
content=self.data[eoi+1:]
大小=长度(内容)
#获取lshift数组
lshift=[i表示已排序(集合(内容))中的符号,如果x==symbol,则表示枚举(内容)中的i,x]
#恢复
还原=“”
对于范围内的i(尺寸):
索引=lshift[索引]
如果索引>=大小:中断
还原+=内容[索引]
#恢复原状
恢复原状

谢谢你,约翰

找到了答案!该算法基于以下假设:字符串连接到最后一个字符,该字符是唯一的,并且在词典学上比字符串中的任何其他字符都小。但是,由于我打算对任何给定字符使用0-255范围内的任何值,因此我不需要额外的符号。幸运的是,还有一些额外的b