Преобразование Барроуза-Уилера — различия между версиями
(→Описание алгоритма) |
Evarand (обсуждение | вклад) (Доказательство корректности наивного алгоритма) |
||
Строка 1: | Строка 1: | ||
== Определение == | == Определение == | ||
− | '''Преобразование Барроуза {{---}} Уилера''' {{---}} алгоритм, используемый для предварительной обработки данных перед сжатием, разработанный для улучшения эффективности последующего кодирования. Преобразование Барроуза {{---}} Уилера меняет порядок символов во входной строке таким образом, что повторяющиеся подстроки образуют на выходе идущие подряд последовательности одинаковых символов. | + | '''Преобразование Барроуза {{---}} Уилера''' (англ. ''Burrows-Wheeler transform'') {{---}} алгоритм, используемый для предварительной обработки данных перед сжатием, разработанный для улучшения эффективности последующего кодирования. Преобразование Барроуза {{---}} Уилера меняет порядок символов во входной строке таким образом, что повторяющиеся подстроки образуют на выходе идущие подряд последовательности одинаковых символов. |
== Описание алгоритма == | == Описание алгоритма == | ||
Преобразование выполняется в три этапа. | Преобразование выполняется в три этапа. | ||
− | * | + | * Составляется таблица всех циклических сдвигов входной строки. |
* Производится лексикографическая (в алфавитном порядке) сортировка строк таблицы. | * Производится лексикографическая (в алфавитном порядке) сортировка строк таблицы. | ||
− | * В качестве выходной строки | + | * В качестве выходной строки выбирается последний столбец таблицы преобразования и номер строки, совпадающей с исходной. |
== Пример работы алгоритма == | == Пример работы алгоритма == | ||
− | Пусть нам дана исходная строка <tex>s = </tex> | + | Пусть нам дана исходная строка <tex>$s =$</tex> "ABACABA". |
{| border="1" | {| border="1" | ||
Строка 38: | Строка 38: | ||
CABAABA | CABAABA | ||
| | | | ||
− | BCABAAA | + | BCABAAA, 3 |
|} | |} | ||
− | Результат можно записать так: <tex>BWT(s)=</tex> | + | Результат можно записать так: <tex>$BWT(s) = $(</tex>"BCABAAA", 3<tex>)</tex>, где 3 {{---}} номер исходной строки в отсортированной матрице. Он нужен для обратного преобразования. |
− | Следует заметить, что иногда в исходной строке приводится | + | Следует заметить, что иногда в исходной строке приводится так называемый символ конца строки ''$'', который в преобразовании будет считаться последним (максимальным) символом, тогда сохранение номера исходной строки не требуется. |
− | Пусть нам дана исходная строка <tex>s = </tex> | + | Пусть нам дана исходная строка <tex>$s =$</tex> "ABACABA$". |
{| border="1" | {| border="1" | ||
Строка 81: | Строка 81: | ||
− | При аналогичном вышеприведённом преобразовании та строчка в матрице, которая будет заканчиваться на символ конца строки и будет исходной: ( | + | При аналогичном вышеприведённом преобразовании та строчка в матрице, которая будет заканчиваться на символ конца строки, и будет исходной: ("ABACABA$"). Тогда результат можно записать так: <tex>$BWT(s) =$</tex> "$CBBAAAA". |
== Обратное преобразование == | == Обратное преобразование == | ||
Строка 87: | Строка 87: | ||
===Наивный алгоритм=== | ===Наивный алгоритм=== | ||
− | Пусть нам дано: <tex>BWT(s)=</tex> | + | Пусть нам дано: <tex>$BWT(s) =$(</tex>"BCABAAA", 3<tex>)</tex>. Тогда выпишем в столбик нашу преобразованную последовательность символов "BCABAAA". Запишем её как последний столбик предыдущей матрицы (при прямом преобразовании Барроуза {{---}} Уилера), при этом все предыдущие столбцы оставляем пустыми. Далее построчно отсортируем матрицу, затем в предыдущий столбец запишем "BCABAAA". Опять построчно отсортируем матрицу. Продолжая таким образом, можно восстановить полный список всех циклических перестановок строки, которую нам надо найти. Выстроив полный отсортированный список перестановок, выберем строку с номером, который нам был изначально дан. В итоге мы получим искомую строку. |
Алгоритм обратного преобразования описан в таблице ниже: | Алгоритм обратного преобразования описан в таблице ниже: | ||
Строка 224: | Строка 224: | ||
|} | |} | ||
− | Следует также заметить, что если нам было бы дано <tex>BWT(s)=</tex> | + | Следует также заметить, что если нам было бы дано <tex>$BWT(s) = $</tex> "$CBBAAAA", то мы также получили бы нашу исходную строку, только с символом конца строки ''$'' на конце: ''ABACABA$''. |
+ | |||
+ | Временная сложность данного алгоритма <tex>O(N^3\log{N}) </tex>, пространственная <tex>O(N^2)</tex>. | ||
+ | |||
+ | ===Доказательство корректности=== | ||
+ | |||
+ | Пусть дана строка <tex>$s$</tex>, к которой было применено преобразование BWT. Докажем, что при использовании наивного алгоритма на каждом шаге получающийся набор строк соответствует суффиксам циклических перестановок исходной строки, методом математической индукции. | ||
+ | * База. Циклически сдвинем все строки исходной таблицы на 1 влево. Тогда в столбце <tex>n</tex> будут находиться символы, добавленные на первом шаге алгоритма, а в столбце <tex>n - 1</tex> символы, изначально стоявшие в таблице до первого шага алгоритма. Таким образом, полученные на первом шаге алгоритма строки являются суффиксами циклических перестановок строки <tex>$s$</tex>. | ||
+ | * Предположение. Пусть на <tex>k</tex> шаге алгоритма все полученные строки являются суффиксами циклических перестановок строки <tex>$s$</tex>. | ||
+ | * Переход. Рассмотрим <tex>k+1</tex>-ый шаг алгоритма. Все строки отсортированы, поэтому самый левый столбец совпадет с 1 столбцом исходной таблицы. Циклически сдвинем все строки исходной таблицы на <tex>n - k</tex> символов вправо. Теперь по предположению первые <tex>k</tex> символов справа в каждой строке совпадают у исходной таблицы и у таблицы, полученной в результате работы алгоритма. <tex>k</tex>-ые справа столбцы также совпадают. Добавленный на <tex>k+1</tex>-ом шаге столбец также совпадает с <tex>k+1</tex>-ым справа столбцом сдвинутой исходной таблицы, так как совпадает с последним столбцом исходной таблицы, которая была сдвинута на <tex>n-k</tex>. | ||
+ | |||
+ | {|border ="1" | ||
+ | !colspan="3" | <tex>$k+1$</tex> шаг алгоритма при <tex>$k=3$</tex> | ||
+ | |- | ||
+ | ! Исходная <br /> таблица || Сдвинутая <br /> таблица || Результат <br /> работы <br /> алгоритма | ||
+ | |-align="center" | ||
+ | | | ||
+ | <font color="red">A</font><font color="green">ABA</font>CA<font color="blue">B</font> | ||
+ | <font color="red">A</font><font color="green">BAA</font>BA<font color="blue">C</font> | ||
+ | <font color="red">A</font><font color="green">BAC</font>AB<font color="blue">A</font> | ||
+ | <font color="red">A</font><font color="green">CAB</font>AA<font color="blue">B</font> | ||
+ | <font color="red">B</font><font color="green">AAB</font>AC<font color="blue">A</font> | ||
+ | <font color="red">B</font><font color="green">ACA</font>BA<font color="blue">A</font> | ||
+ | <font color="red">C</font><font color="green">ABA</font>AB<font color="blue">A</font> | ||
+ | | | ||
+ | CA<font color="blue">B</font><font color="red">A</font><font color="green">ABA</font> | ||
+ | BA<font color="blue">C</font><font color="red">A</font><font color="green">BAA</font> | ||
+ | AB<font color="blue">A</font><font color="red">A</font><font color="green">BAC</font> | ||
+ | AA<font color="blue">B</font><font color="red">A</font><font color="green">CAB</font> | ||
+ | AC<font color="blue">A</font><font color="red">B</font><font color="green">AAB</font> | ||
+ | BA<font color="blue">A</font><font color="red">B</font><font color="green">ACA</font> | ||
+ | AB<font color="blue">A</font><font color="red">C</font><font color="green">ABA</font> | ||
+ | | | ||
+ | <font color="blue">B</font><font color="red">A</font><font color="green">ABA</font> | ||
+ | <font color="blue">C</font><font color="red">A</font><font color="green">BAA</font> | ||
+ | <font color="blue">A</font><font color="red">A</font><font color="green">BAC</font> | ||
+ | <font color="blue">B</font><font color="red">A</font><font color="green">CAB</font> | ||
+ | <font color="blue">A</font><font color="red">B</font><font color="green">AAB</font> | ||
+ | <font color="blue">A</font><font color="red">B</font><font color="green">ACA</font> | ||
+ | <font color="blue">A</font><font color="red">C</font><font color="green">ABA</font> | ||
+ | |- | ||
+ | |} | ||
− | + | Таким образом, поскольку на каждом шаге алгоритма получившиеся строки являлись суффиксами циклических перестановок <tex> $s$ </tex>, после последнего шага получившиеся строки будут совпадать с циклическими перестановками <tex> $s$ </tex>. | |
===Оптимизация=== | ===Оптимизация=== | ||
Строка 256: | Строка 297: | ||
|} | |} | ||
− | Здесь слева | + | Здесь слева отсортированный данный столбец, чтобы мы знали, какое место в лексикографическом порядке занимает приписываемый нами символ среди всех элементов данного нам изначально столбца. Справа - изначально данный столбец и соответствующее ему число. Поскольку в нашем алгоритме новый столбец приписывается в начало, то мы из состояния <tex> i </tex> (левый столбец) переходим в состояние <tex> j </tex> (правый). Для того, чтобы восстановить строку, нам необходимо от последней такой цифры по пути из <tex> j </tex> в <tex> i </tex> восстановить строку. |
{| | {| | ||
| | | | ||
Строка 305: | Строка 346: | ||
|} | |} | ||
===Сложность оптимизированного алгоритма=== | ===Сложность оптимизированного алгоритма=== | ||
− | Данный алгоритм работает за <tex>O( | + | Данный алгоритм работает за <tex>O(N\log{N})</tex> времени и требует <tex>O(N)</tex> памяти. Однако, если размер алфавита не очень большой, то для выяснения первого столбца матрицы можно использовать сортировку подсчетом, в этом случае алгоритм работает за <tex>O(N+M)</tex> действий и требует <tex>O(N+M)</tex> памяти, где <tex>M</tex> — размер алфавита. |
===Псевдокод оптимизированного алгоритма=== | ===Псевдокод оптимизированного алгоритма=== |
Версия 16:51, 6 декабря 2015
Содержание
Определение
Преобразование Барроуза — Уилера (англ. Burrows-Wheeler transform) — алгоритм, используемый для предварительной обработки данных перед сжатием, разработанный для улучшения эффективности последующего кодирования. Преобразование Барроуза — Уилера меняет порядок символов во входной строке таким образом, что повторяющиеся подстроки образуют на выходе идущие подряд последовательности одинаковых символов.
Описание алгоритма
Преобразование выполняется в три этапа.
- Составляется таблица всех циклических сдвигов входной строки.
- Производится лексикографическая (в алфавитном порядке) сортировка строк таблицы.
- В качестве выходной строки выбирается последний столбец таблицы преобразования и номер строки, совпадающей с исходной.
Пример работы алгоритма
Пусть нам дана исходная строка
"ABACABA".Трансформация | |||
---|---|---|---|
Вход | Все Перестановки |
Сортировка Строк |
Выход |
ABACABA |
ABACABA BACABAA ACABAAB CABAABA ABAABAC BAABACA AABACAB |
AABACAB ABAABAC ABACABA ACABAAB BAABACA BACABAA CABAABA |
BCABAAA, 3 |
Результат можно записать так:
"BCABAAA", 3 , где 3 — номер исходной строки в отсортированной матрице. Он нужен для обратного преобразования.
Следует заметить, что иногда в исходной строке приводится так называемый символ конца строки $, который в преобразовании будет считаться последним (максимальным) символом, тогда сохранение номера исходной строки не требуется.
Пусть нам дана исходная строка "ABACABA$".
Трансформация | |||
---|---|---|---|
Вход | Все Перестановки |
Сортировка Строк |
Выход |
ABACABA$ |
ABACABA$ BACABA$A ACABA$AB CABA$ABA ABA$ABAC BA$ABACA A$ABACAB $ABACABA |
ABACABA$ ABA$ABAC ACABA$AB A$ABACAB BACABA$A BA$ABACA CABA$ABA $ABACABA |
$CBBAAAA |
При аналогичном вышеприведённом преобразовании та строчка в матрице, которая будет заканчиваться на символ конца строки, и будет исходной: ("ABACABA$"). Тогда результат можно записать так:
"$CBBAAAA".Обратное преобразование
Наивный алгоритм
Пусть нам дано:
"BCABAAA", 3 . Тогда выпишем в столбик нашу преобразованную последовательность символов "BCABAAA". Запишем её как последний столбик предыдущей матрицы (при прямом преобразовании Барроуза — Уилера), при этом все предыдущие столбцы оставляем пустыми. Далее построчно отсортируем матрицу, затем в предыдущий столбец запишем "BCABAAA". Опять построчно отсортируем матрицу. Продолжая таким образом, можно восстановить полный список всех циклических перестановок строки, которую нам надо найти. Выстроив полный отсортированный список перестановок, выберем строку с номером, который нам был изначально дан. В итоге мы получим искомую строку. Алгоритм обратного преобразования описан в таблице ниже:Обратное преобразование | |||||||
---|---|---|---|---|---|---|---|
Вход | |||||||
BCABAAA | |||||||
Добавление 1 | Сортировка 1 | Добавление 2 | Сортировка 2 | Добавление 3 | Сортировка 3 | Добавление 4 | |
B C A B A A A |
A A A A B B C |
BA CA AA BA AB AB AC |
AA AB AB AC BA BA CA |
BAA CAB AAB BAC ABA ABA ACA |
AAB ABA ABA ACA BAA BAC CAB |
BAAB CABA AABA BACA ABAA ABAC ACAB | |
Сортировка 4 | Добавление 5 | Сортировка 5 | Добавление 6 | Сортировка 6 | Добавление 7 | Сортировка 7 | |
AABA ABAA ABAC ACAB BAAB BACA CABA |
BAABA CABAA AABAC BACAB ABAAB ABACA ACABA |
AABAC ABAAB ABACA ACABA BAABA BACAB CABAA |
BAABAC CABAAB AABACA BACABA ABAABA ABACAB ACABAA |
AABACA ABAABA ABACAB ACABAA BAABAC BACABA CABAAB |
BAABACA CABAABA AABACAB BACABAA ABAABAC ABACABA ACABAAB |
AABACAB ABAABAC ABACABA ACABAAB BAABACA BACABAA CABAABA | |
Результат | |||||||
ABACABA |
Следует также заметить, что если нам было бы дано
"$CBBAAAA", то мы также получили бы нашу исходную строку, только с символом конца строки $ на конце: ABACABA$.Временная сложность данного алгоритма
, пространственная .Доказательство корректности
Пусть дана строка
, к которой было применено преобразование BWT. Докажем, что при использовании наивного алгоритма на каждом шаге получающийся набор строк соответствует суффиксам циклических перестановок исходной строки, методом математической индукции.- База. Циклически сдвинем все строки исходной таблицы на 1 влево. Тогда в столбце будут находиться символы, добавленные на первом шаге алгоритма, а в столбце символы, изначально стоявшие в таблице до первого шага алгоритма. Таким образом, полученные на первом шаге алгоритма строки являются суффиксами циклических перестановок строки .
- Предположение. Пусть на шаге алгоритма все полученные строки являются суффиксами циклических перестановок строки .
- Переход. Рассмотрим -ый шаг алгоритма. Все строки отсортированы, поэтому самый левый столбец совпадет с 1 столбцом исходной таблицы. Циклически сдвинем все строки исходной таблицы на символов вправо. Теперь по предположению первые символов справа в каждой строке совпадают у исходной таблицы и у таблицы, полученной в результате работы алгоритма. -ые справа столбцы также совпадают. Добавленный на -ом шаге столбец также совпадает с -ым справа столбцом сдвинутой исходной таблицы, так как совпадает с последним столбцом исходной таблицы, которая была сдвинута на .
шаг алгоритма при | ||
---|---|---|
Исходная таблица |
Сдвинутая таблица |
Результат работы алгоритма |
AABACAB ABAABAC ABACABA ACABAAB BAABACA BACABAA CABAABA |
CABAABA BACABAA ABAABAC AABACAB ACABAAB BAABACA ABACABA |
BAABA CABAA AABAC BACAB ABAAB ABACA ACABA |
Таким образом, поскольку на каждом шаге алгоритма получившиеся строки являлись суффиксами циклических перестановок
, после последнего шага получившиеся строки будут совпадать с циклическими перестановками .Оптимизация
Однако, данный алгоритм можно оптимизировать. Заметим, что при каждом проявлении неизвестного столбца выполнялись одни и те же действия. Мы приписывали новый столбец и сортировали имеющиеся данные. На каждом шагу мы к строке, которая находилась на
-ом месте приписываем в начало -ый элемент столбца входных данных. Пусть изначально мы знаем каким по порядку является приписанный нами в начало символ (то есть каким по порядку в столбце). И конечно же мы знаем исходя из предыдущего шага какое место занимала наша строка без этого первого символа ( -ое). Тогда несложно заметить, что при выполнении такой операции строка с номером всегда будет перемещаться на позицию с номером .0 | а | р | 9 | |
1 | а | д | 7 | |
2 | а | a | 0 | |
3 | а | к | 8 | |
4 | а | р | 10 | |
5 | б | a | 1 | |
6 | б | a | 2 | |
7 | д | a | 3 | |
8 | к | a | 4 | |
9 | р | б | 5 | |
10 | р | б | 6 |
Здесь слева отсортированный данный столбец, чтобы мы знали, какое место в лексикографическом порядке занимает приписываемый нами символ среди всех элементов данного нам изначально столбца. Справа - изначально данный столбец и соответствующее ему число. Поскольку в нашем алгоритме новый столбец приписывается в начало, то мы из состояния
(левый столбец) переходим в состояние (правый). Для того, чтобы восстановить строку, нам необходимо от последней такой цифры по пути из в восстановить строку.
Сложность оптимизированного алгоритмаДанный алгоритм работает за времени и требует памяти. Однако, если размер алфавита не очень большой, то для выяснения первого столбца матрицы можно использовать сортировку подсчетом, в этом случае алгоритм работает за действий и требует памяти, где — размер алфавита.Псевдокод оптимизированного алгоритмаПусть — количество символов во входной строке, — количество символов в алфавите, — номер исходной строки в матрице перестановок, — входящая строка, — массив для сортировки подсчетом, — вектор обратного преобразования, — номер данной нам строки в таблице.// Cчитаем частоты символов for i = 0 .. M count[i] = 0 for i = 0 .. N count[s[i]]++ // Упорядочиваем символы, чтобы получить первый столбец исходной матрицы // count[i] указывает на первую позицию символа i в первом столбце sum = 0 for i = 0 .. M sum = sum + count[i] count[i] = sum - count[i] // Cоздаем вектор обратного преобразования for i = 0 .. N t[count[s[i]]] = i count[s[i]]++ // И восстанавливаем исходный текст j = t[x] for i = 0 .. N print(s[j]) j = t[j] Доказательство корректностиПусть текст состоит из символов, занумерованных с нуля: . Буквы принадлежат некоторому алфавиту . Лексикографический порядок (строгий) на строках из алфавита будем обозначать . Обозначим через циклический сдвиг текста на символов влево:Существует перестановка чисел , которая удовлетворяет условию:Преобразование Барроуза-Уилера текста есть текст , буквы которого заданы соотношением:Пусть — перестановка чисел , удовлетворяющая условию:и в случае равенства и выполнено — . Перестановка однозначно определяется текстом и ее можно посчитать за , используя сортировку подсчетом. Рассмотрим перестановку как отображение . Пусть копмозиция отображений , где .
Дополнительно
Ссылки |