Skip to content

Commit 9ebed56

Browse files
committed
feat(js): add modular solution and documentation for hard challenge 3 - Suffix Array Construction
1 parent fc349fe commit 9ebed56

File tree

3 files changed

+205
-0
lines changed

3 files changed

+205
-0
lines changed
Lines changed: 131 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,131 @@
1+
# Suffix Array Construction
2+
3+
## English
4+
5+
The suffix array is a powerful data structure used in string processing to enable efficient pattern searches and substring queries. This challenge involves constructing the suffix array and the LCP (Longest Common Prefix) array for a given string.
6+
7+
The suffix array is built by sorting all suffixes of the string. The LCP array stores the length of the longest common prefix between consecutive suffixes in the suffix array, which helps speed up pattern matching and other string processing tasks.
8+
9+
### Relevant Code Snippet
10+
11+
```javascript
12+
class SuffixArray {
13+
constructor(text) {
14+
this.text = text;
15+
this.n = text.length;
16+
this.suffixArray = [];
17+
this.lcpArray = [];
18+
}
19+
20+
buildSuffixArray() {
21+
this.suffixArray = Array.from({ length: this.n }, (_, i) => i);
22+
this.suffixArray.sort((a, b) => {
23+
const substrA = this.text.substring(a);
24+
const substrB = this.text.substring(b);
25+
if (substrA < substrB) return -1;
26+
if (substrA > substrB) return 1;
27+
return 0;
28+
});
29+
return this.suffixArray;
30+
}
31+
32+
buildLCPArray() {
33+
if (this.suffixArray.length === 0) {
34+
this.buildSuffixArray();
35+
}
36+
37+
this.lcpArray = new Array(this.n).fill(0);
38+
const invSuffix = new Array(this.n);
39+
40+
for (let i = 0; i < this.n; i++) {
41+
invSuffix[this.suffixArray[i]] = i;
42+
}
43+
44+
let k = 0;
45+
for (let i = 0; i < this.n; i++) {
46+
if (invSuffix[i] === this.n - 1) {
47+
k = 0;
48+
continue;
49+
}
50+
const j = this.suffixArray[invSuffix[i] + 1];
51+
while (i + k < this.n && j + k < this.n && this.text[i + k] === this.text[j + k]) {
52+
k++;
53+
}
54+
this.lcpArray[invSuffix[i]] = k;
55+
if (k > 0) k--;
56+
}
57+
58+
return this.lcpArray;
59+
}
60+
}
61+
```
62+
63+
### History
64+
65+
Suffix arrays and LCP arrays are fundamental data structures in string processing, enabling efficient pattern matching, substring queries, and bioinformatics applications. They are a space-efficient alternative to suffix trees.
66+
67+
---
68+
69+
## Español
70+
71+
El arreglo de sufijos es una estructura de datos poderosa utilizada en el procesamiento de cadenas para permitir búsquedas eficientes de patrones y consultas de subcadenas. Este reto consiste en construir el arreglo de sufijos y el arreglo LCP (Longest Common Prefix) para una cadena dada.
72+
73+
El arreglo de sufijos se construye ordenando todos los sufijos de la cadena. El arreglo LCP almacena la longitud del prefijo común más largo entre sufijos consecutivos en el arreglo de sufijos, lo que ayuda a acelerar la búsqueda de patrones y otras tareas de procesamiento de cadenas.
74+
75+
### Fragmento de Código Relevante
76+
77+
```javascript
78+
class SuffixArray {
79+
constructor(text) {
80+
this.text = text;
81+
this.n = text.length;
82+
this.suffixArray = [];
83+
this.lcpArray = [];
84+
}
85+
86+
buildSuffixArray() {
87+
this.suffixArray = Array.from({ length: this.n }, (_, i) => i);
88+
this.suffixArray.sort((a, b) => {
89+
const substrA = this.text.substring(a);
90+
const substrB = this.text.substring(b);
91+
if (substrA < substrB) return -1;
92+
if (substrA > substrB) return 1;
93+
return 0;
94+
});
95+
return this.suffixArray;
96+
}
97+
98+
buildLCPArray() {
99+
if (this.suffixArray.length === 0) {
100+
this.buildSuffixArray();
101+
}
102+
103+
this.lcpArray = new Array(this.n).fill(0);
104+
const invSuffix = new Array(this.n);
105+
106+
for (let i = 0; i < this.n; i++) {
107+
invSuffix[this.suffixArray[i]] = i;
108+
}
109+
110+
let k = 0;
111+
for (let i = 0; i < this.n; i++) {
112+
if (invSuffix[i] === this.n - 1) {
113+
k = 0;
114+
continue;
115+
}
116+
const j = this.suffixArray[invSuffix[i] + 1];
117+
while (i + k < this.n && j + k < this.n && this.text[i + k] === this.text[j + k]) {
118+
k++;
119+
}
120+
this.lcpArray[invSuffix[i]] = k;
121+
if (k > 0) k--;
122+
}
123+
124+
return this.lcpArray;
125+
}
126+
}
127+
```
128+
129+
### Historia
130+
131+
Los arreglos de sufijos y los arreglos LCP son estructuras de datos fundamentales en el procesamiento de cadenas, que permiten búsquedas eficientes de patrones, consultas de subcadenas y aplicaciones en bioinformática. Son una alternativa eficiente en espacio a los árboles de sufijos.
Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
// SuffixArray.js - Suffix Array and LCP Array construction in JavaScript
2+
3+
class SuffixArray {
4+
constructor(text) {
5+
this.text = text;
6+
this.n = text.length;
7+
this.suffixArray = [];
8+
this.lcpArray = [];
9+
}
10+
11+
buildSuffixArray() {
12+
this.suffixArray = Array.from({ length: this.n }, (_, i) => i);
13+
this.suffixArray.sort((a, b) => {
14+
const substrA = this.text.substring(a);
15+
const substrB = this.text.substring(b);
16+
if (substrA < substrB) return -1;
17+
if (substrA > substrB) return 1;
18+
return 0;
19+
});
20+
return this.suffixArray;
21+
}
22+
23+
buildLCPArray() {
24+
if (this.suffixArray.length === 0) {
25+
this.buildSuffixArray();
26+
}
27+
28+
this.lcpArray = new Array(this.n).fill(0);
29+
const invSuffix = new Array(this.n);
30+
31+
for (let i = 0; i < this.n; i++) {
32+
invSuffix[this.suffixArray[i]] = i;
33+
}
34+
35+
let k = 0;
36+
for (let i = 0; i < this.n; i++) {
37+
if (invSuffix[i] === this.n - 1) {
38+
k = 0;
39+
continue;
40+
}
41+
const j = this.suffixArray[invSuffix[i] + 1];
42+
while (i + k < this.n && j + k < this.n && this.text[i + k] === this.text[j + k]) {
43+
k++;
44+
}
45+
this.lcpArray[invSuffix[i]] = k;
46+
if (k > 0) k--;
47+
}
48+
49+
return this.lcpArray;
50+
}
51+
}
52+
53+
export default SuffixArray;
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
/*
2+
Challenge:
3+
Construct a suffix array and LCP array for a given string to enable efficient pattern searches.
4+
5+
This solution follows DRY principles and is implemented in JavaScript.
6+
*/
7+
8+
import SuffixArray from './SuffixArray.js';
9+
10+
function main() {
11+
const text = "banana";
12+
const suffixArrayObj = new SuffixArray(text);
13+
14+
const suffixArray = suffixArrayObj.buildSuffixArray();
15+
console.log("Suffix Array:", suffixArray);
16+
17+
const lcpArray = suffixArrayObj.buildLCPArray();
18+
console.log("LCP Array:", lcpArray);
19+
}
20+
21+
main();

0 commit comments

Comments
 (0)