当前位置: 首页 > 工具软件 > bwt > 使用案例 >

BWT算法解析及Java语言实现

归俊
2023-12-01

BWT算法将原来的文本转换为一个相似的文本,转换后使得相同的字符位置连续或者相邻,之后可以使用其他技术如:Move-to-fronttransform  游程编码 进行文本压缩。

BWT原理:

1. BWT编码

对需要转换的字符串后加“$”符号($作为标识符,保证n个循环移位后的字符串均布相同),进行循环右移,每次循环一位,记录下每次右移后的结果。

对循环移位后得到的n个字符串按照字典序排序。

记录下排序后得到的每个字符串的最后一个字符(得到L字符串)和第一个字符(得到F列)。

例如:apple

序号

移位记录M

排序后NM

F

L

1

apple$

$apple

$

e

2

$apple

apple$

a

$

3

e$appl

e$appl

e

l

4

le$app

le$app

l

p

5

ple$ap

ple$ap

p

p

6

pple$a

pple$a

p

a

 

2. BWT解码

因为进行的是循环移位,有如下性质:

①  L的第一个元素是输入字符串中的最后一个元素

②  同一行中F是L的下一个元素,L是F的前一个元素。

所以我们就可以得到:

①  F字符串可由L字符串推理得到

②  由于F序列中的字符与其相对位置和L序列中的字符与其相对位置是相对应的。因此,在每个字符串中,我们需要记录每个字符的相对位置(相对位置即指在本序列中该字符出现的第几次),例如:

 

F序列

$

a

e

l

p

p

相对位置

1

1

1

1

1

2

L序列

e

$

l

p

p

a

相对位置

1

1

1

1

2

1

 

根据上表,我们可得出原来的字符串:

如上例:字符串最后一位是e,根据L序列的e字符及其相对位置1,找到F序列中对应的(字符e及其相对位置1), 与F序列的e字符及其相对位置1的同一行L序列字符为l其相对位置为1,所以原字符串e的前一位为l。以此类推,可得到原字符串。


参考:http://blog.csdn.net/blackjack_/article/details/73801003

          https://www.cnblogs.com/xudong-bupt/p/3763814.html



Java语言实现:

package bwt;

import java.util.Arrays;
import java.util.Scanner;

public class bwt2 {

    public static void main(String[] args) {
        System.out.print("请输入字符串:");
        Scanner sc = new Scanner(System.in);
        String str = sc.nextLine();
        String enCodeStr = enCode(str);
        System.out.println("编码后的字符串是:"+enCodeStr.split(":")[0]);
        System.out.println("解码后的字符串是:"+deCode(enCodeStr.split(":")[0],enCodeStr.split(":")[1]));
    }

    // bwt编码
    public static String enCode(String line) {
        String str = line+"$";
        int len = str.length();
        char[] charArray = str.toCharArray();
        char[][] ch = new char[len][len];
        char[] c_tmp = charArray.clone();
        for (int i = 0; i < len; i++) {
            for (int j = 0; j < len; j++) {
                ch[i][j] = c_tmp[j];
            }
            char zj = c_tmp[len-1];
            for(int k = len-1;k>0;k--){
                c_tmp[k]=c_tmp[k-1];
            }
            c_tmp[0]=zj;
        }
        String[] strings = new String[len];
        for (int i = 0; i < len; i++) {
            StringBuffer chline = new StringBuffer();
            for (char c : ch[i]) {
                chline.append(c);
            }
            strings[i] = chline.toString();
        }
        Arrays.sort(strings);
        StringBuffer sBuffer = new StringBuffer();
        StringBuffer sBuffer2 = new StringBuffer();
        for (String s : strings) {
            sBuffer.append(s.substring(len - 1, len));
        }
        for (String s2 : strings) {
            sBuffer2.append(s2.substring(0, 1));
        }
        return sBuffer.toString()+":"+sBuffer2.toString();
    }

    // bwt解码
    public static String deCode(String str1,String str2) {
        int len=str1.length();
        char[] L = str1.toCharArray();
        char[] F = str2.toCharArray();
        int [] L1=new int[len];
        int [] F1=new int[len];
        for(int i=0;i<len;i++){
            L1[i]=1;
            F1[i]=1;
        }
        for(int i=0;i<len-1;i++){
            int num = 1;
            int num1 = 1;
            for(int j=i+1;j<len;j++){
                if(L[i]==L[j] && L1[j]==1){
                    num++;
                    L1[j]=num;
                }
                if(F[i]==F[j] && F1[j]==1){
                    num1++;
                    F1[j]=num1;
                }
            }
        }
        char result[]=new char[len];
        result[len-1]='$';
        result[len-2]=L[0];
        int newlen=len-2;
        int n1=0;
        while(newlen>0){
            for (int i=0;i<len;i++){
                if(F[i]==L[n1] && L1[n1]==F1[i]){
                    newlen--;
                    result[newlen]=L[i];
                    n1=i;
                    break;
                }
            }
        }
        String resultline = "";
        for(int i=0;i<len-1;i++){
            resultline=resultline+result[i];
        }
        return resultline;
    }
}


 类似资料: