원 논문의 제목은 A Constant-Space Comparison-Based Algorithm for Computing the Burrows–Wheeler Transform이다. 원문 내용의 2절의 일부는 다음과 같다. 다음 내용은 0-index 기반이다. 즉, 문자열에서 첫 문자는 index 0을 가진다. 가령, T='temp'에서 T[0] == 't'이고, T[3] == 'p'이다.
Given the input text T = T [0 ..n−1] where T [n−1] = ,movingasinglecharacterinsideTcanchangethecontentofmanysuffixes.TheideatocircumventthisdifficultywithoutusingstorageforthesuffixsortistoproceedbyinductionfromrighttoleftinT,whilemaintainingtheBWTofthecurrentsuffixTs,denotedbyBWT(Ts).Weassume0≤s≤n−3,sincethelasttwosuffixesofTareequaltotheirrespectiveBWT.TocomputeBWT(Ts),supposethatBWT(Ts+1)hasbeenalreadycomputedandstoredinthelastpositionsofT,i.e.T[s+1..n−1].Considerthecurrentsymbolc=T[s]:ifwelookatthecontentofT[s..n−1],wenolongerfindTs,butthesymbolcfollowedbythepermutationBWT(Ts+1)ofTs+1.Nevertheless,westillhaveenoughinformationaswewillshowintheproofofTheorem1thatthepositionof,movingasinglecharacterinsideTcanchangethecontentofmanysuffixes.TheideatocircumventthisdifficultywithoutusingstorageforthesuffixsortistoproceedbyinductionfromrighttoleftinT,whilemaintainingtheBWTofthecurrentsuffixTs,denotedbyBWT(Ts).Weassume0≤s≤n−3,sincethelasttwosuffixesofTareequaltotheirrespectiveBWT.TocomputeBWT(Ts),supposethatBWT(Ts+1)hasbeenalreadycomputedandstoredinthelastpositionsofT,i.e.T[s+1..n−1].Considerthecurrentsymbolc=T[s]:ifwelookatthecontentofT[s..n−1],wenolongerfindTs,butthesymbolcfollowedbythepermutationBWT(Ts+1)ofTs+1.Nevertheless,westillhaveenoughinformationaswewillshowintheproofofTheorem1thatthepositionof inside BWT(Ts+1) is related to the rank of Ts+1 among the suffixes Ts+1, ... , Tn−1. We exploit this fact in the following steps.
1. Find the position p of the inT[s+1..n−1]:notethatp−sisthe(local)rankofthesuffixTs+1thatoriginallywasstartingatpositions+1.2.FindtherankrofthesuffixTs(originallyinpositions)usingjustsymbolc.Tothisend,scanT[s+1..n−1]andcounthowmanysymbolsarestrictlysmallerthancandhowmanyoccurrencesofcappearinT[s+1..p](andaddsasanoffsettoobtainr).3.StorecintoT[p](thusreplacingtheinT[s+1..n−1]:notethatp−sisthe(local)rankofthesuffixTs+1thatoriginallywasstartingatpositions+1.2.FindtherankrofthesuffixTs(originallyinpositions)usingjustsymbolc.Tothisend,scanT[s+1..n−1]andcounthowmanysymbolsarestrictlysmallerthancandhowmanyoccurrencesofcappearinT[s+1..p](andaddsasanoffsettoobtainr).3.StorecintoT[p](thusreplacingthe).
4. Insert the symbol $ in T[r] by shifting T[s+1 .. r] by one position left.
해석하면 다음과 같다.
입력 문자열 T = T[0..n-1]이 있고, T[n-1] = $일 때, T 안의 단일 문자열을 이동시키는 것은 많은 접미사들의 내용을 바꿀 수 있다. 접미사 정렬을 위해 공간을 사용하는 어려움을 극복하기 위한 아이디어는 현재 접미사 Ts의 BWT(BWT(Ts)로 표기함)를 유지하면서 T에서 오른쪽에서 왼쪽으로 유도하면서 진행하는 것이다. 우리는 0 ≤ s ≤ n−3를 가정하는데, 이는 T의 마지막 두 접미사가 그들의 관련 BWT와 같기 때문이다.
BWT(Ts)를 계산하기 위해서, BWT(Ts+1)이 이미 계산되었고, T의 마지막 위치에, 가령 T[s+1 .. n-1]에 저장되었다고 하자. 현재 문자 c = T[s]를 고려하자: 만약, 우리가 T[s .. n-1]의 내용을 살펴보면, 우리는 더 이상 Ts를 찾을 수 없다. 하지만, 이 때 기호 c를 발견할 수 있고 기호 c 다음에는 Ts+1의 순열 BWT(Ts+1)이 따라온다. 그럼에도 불구하고, 이론 1의 증명에서 보이듯이 우리는 충분한 정보를 가지고 있다. 이론 1의 증명은 BWT(Ts+1)의 내부에 있는 $의 위치는 Ts+1, ... , Tn-1 중에서 Ts+1의 랭크와 관련이 있다. 우리는 다음 단계들에서 이 사실을 이용한다.
1. T[s+1 .. n-1]에서 $의 위치를 찾는다: p-s는 원래 s+1위치에서 시작하는 접미사 Ts+1의 (지역) 랭크임을 명심하자.
2. 기호 c만을 이용해서 접미사 Ts (원래 s 위치에 있었던)의 랭크 r을 찾는다. 이것을 위해서, 얼마나 많은 문자들이 T[s+1 .. n-1] 범위에서는 엄밀하게(<) c 문자값 보다 작은지와 얼마나 많은 c가 T[s+1 .. p] 범위에서 나타났는지 센다. (그리고 r을 계산하기 위해서 s를 i의 초기값에 오프셋으로서 더한다.)
3. c를 T[p]에 저장한다. (그래서 $을 대체한다).
4. T[s+1 .. r]을 왼쪽 방향으로 한 칸 옮김으로써 T[r]에 기호 $를 넣는다.
다음은 그 아래 부분에 있는 내용을 해석한 것이다.
T = mississippi이고s=4이라고할때,우리는마지막T위치에서부분적으로완성된BWT를대문자로표기했다.우리가마지막7자에대한BWT를이미계산했다고하면,우리는missiIPSPIS를 가진다. 우리는 이제 p = 11을 가진다. 그리고 위치 p보다 작은 위치에 있는 기호 중 이미 처리된 BWT에는 현재의 문자 c(='i') 보다 작은 기호가 하나('′)만있고,c(=′i′)와같은두기호가있기때문에,우리는r=s+3=7을가지게된다.이말은우리가′'를 기호 c(='I')로 교체하고, IPS를 왼쪽으로 한칸 옮겨야 한다는 뜻이며, 이는 '′를위치r에넣는것을의미한다.다음의문자열상태는missIPSPISI가 되며, 이는 Ts의 BWT이다.
이제 좀 더 쉽게 설명을 하겠다. 위의 푸른 부분의 내용을 순서대로 설명하자면, 현재 T는 missiIPSPIS이다.여기에서p는′'의 위치이며 11의 값을 가진다. 이미 처리된 BWT 부분인 IPSPIS에서현재의기호′i′보다작은값을가지는기호는′' 한 개가 있고, '′위치보다작은위치의BWT부분인IPSPIS에서′i′는2개가있다.그러므로r은원래s값보다3만큼큰값인7을가지게된다.여기에서크다작다의기준은ASCII코드값을기준으로하며,′'는 36의 값을 가지며, 각각 i(105), m(109), p(112), 그리고 s(115)의 값을 가진다.
step 1은 s + 1보다 큰 위치에서 END_MARKER의 위치를 찾는다. step 2에서는 s의 위치보다 크고 전체 문자 길이보다 작은 위치[s+1 .. n]의 문자들을 c와 비교하면서 c보다 엄밀하게 작을 경우(<)에 r을 1씩 증가시킨다. s의 위치보다 크고 END_MARKER의 위치보다 작은 위치[s+1 .. p]의 문자 중에 c인 경우 r을 1씩 증가시킨다. 그런 이유로 첫번째 loop에서 <= 기호를 사용한다. END_MARKER의 위치에 현재 문자 c를 넣는다. '$'를 r위치에 넣는다.
다음은 관련 c 코드이다. 실험과 들여쓰기로 인한 불명확함을 제거하기 위해서 약간 수정했다. 또한 개별 단계에 맞게 주석을 수정했다. 가령 string을 매개변수로 받고, 중괄호를 명시적으로 사용했다. END_MARKER는 논문에서는 주로 '$'로 표기된다. 이는 sentinel이라고도 불리며, c나 cpp에서는 보통 '\0'이다.
#include <iostream>
#include <string>
#include <boost/format.hpp>
using namespace std;
const char END_MARKER = '$';
void inplaceBWT(string& T, int n) {
int i, p, r, s;
unsigned char c;
int count = 0;
cout << "step " << ++count << ": " << T << endl;
for (s = n - 3; s >= 0; s--) {
c = T[s];
/* steps 1 and 2 */
r = s;
// step 1: find the position of END_MARKER and store the position in p variable
for (i = s + 1; T[i] != END_MARKER; ++i) {
// count the occurrence of c in T[s+1 .. p]
if (T[i] <= c) {
++r;
}
}
p = i;
// step 2: count the number of characters strictly smaller than c in T[s+1 .. n]
while (i < n) {
if (T[i++] < c) {
++r;
}
}
// step 4: insert '$' at T[r]
T[p] = c;
/* step 4 */
for (i = s; i < r; ++i) {
T[i] = T[i + 1];
}
T[r] = END_MARKER;
cout << "step " << ++count << ": " << T << endl;
}
}
int main() {
string test = "mississipi$";
inplaceBWT(test, test.size());
return 0;
}
n은 전체 문자열 길이이다. s는 알고리즘을 진행할 때, 처리되는 문자의 위치이다. i는 END_MARKER의 위치를 찾는데 사용되는 변수이다. p는 END_MARKER의 위치를 저장하는데 사용되는 변수이다.
댓글