Skip to content

Commit 158bde4

Browse files
committed
Add kmp
1 parent 19aa216 commit 158bde4

File tree

3 files changed

+87
-0
lines changed

3 files changed

+87
-0
lines changed
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
# Thuật toán Knuth–Morris–Pratt
2+
3+
Thuật toán tìm kiếm chuỗi Knuth-Morris-Pratt (hoặc thuật toán KMP) tìm kiếm sự xuất hiện của từ `W` trong chuỗi văn bản chính `T` bằng cách quan sát khi nào sự không phù hợp diễn ra, bản thân từ `W` đã bao gồm các thông tin hữu ích để xác định vị trị bắt đầu của ký tự so sánh tiếp theo, do đó sẽ bỏ qua quá trình kiểm tra lại các ký tự đã so sánh trước đó.
4+
5+
## Độ phức tạp
6+
7+
- **Độ phức tạp thời gian:** `O(|W| + |T|)` (nhanh hơn nhiều so với bình thường `O(|W| * |T|)`)
8+
- **Độ phức tạp không gian:** `O(|W|)`
9+
10+
## Liên kết
11+
12+
- [Wikipedia](https://en.wikipedia.org/wiki/Knuth%E2%80%93Morris%E2%80%93Pratt_algorithm)
13+
- [YouTube](https://www.youtube.com/watch?v=GTJr8OvyEVQ&list=PLLXdhg_r2hKA7DPDsunoDZ-Z769jWn4R8)
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
import knuthMorrisPratt from '../knuthMorrisPratt';
2+
3+
describe('knuthMorrisPratt', () => {
4+
it('should find word position in given text', () => {
5+
expect(knuthMorrisPratt('', '')).toBe(0);
6+
expect(knuthMorrisPratt('a', '')).toBe(0);
7+
expect(knuthMorrisPratt('a', 'a')).toBe(0);
8+
expect(knuthMorrisPratt('abcbcglx', 'abca')).toBe(-1);
9+
expect(knuthMorrisPratt('abcbcglx', 'bcgl')).toBe(3);
10+
expect(knuthMorrisPratt('abcxabcdabxabcdabcdabcy', 'abcdabcy')).toBe(15);
11+
expect(knuthMorrisPratt('abcxabcdabxabcdabcdabcy', 'abcdabca')).toBe(-1);
12+
expect(knuthMorrisPratt('abcxabcdabxaabcdabcabcdabcdabcy', 'abcdabca')).toBe(12);
13+
expect(knuthMorrisPratt('abcxabcdabxaabaabaaaabcdabcdabcy', 'aabaabaaa')).toBe(11);
14+
});
15+
});
Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
1+
/**
2+
* @see https://www.youtube.com/watch?v=GTJr8OvyEVQ
3+
* @param {string} word
4+
* @return {number[]}
5+
*/
6+
function buildPatternTable(word) {
7+
const patternTable = [0];
8+
let prefixIndex = 0;
9+
let suffixIndex = 1;
10+
11+
while (suffixIndex < word.length) {
12+
if (word[prefixIndex] === word[suffixIndex]) {
13+
patternTable[suffixIndex] = prefixIndex + 1;
14+
suffixIndex += 1;
15+
prefixIndex += 1;
16+
} else if (prefixIndex === 0) {
17+
patternTable[suffixIndex] = 0;
18+
suffixIndex += 1;
19+
} else {
20+
prefixIndex = patternTable[prefixIndex - 1];
21+
}
22+
}
23+
24+
return patternTable;
25+
}
26+
27+
/**
28+
* @param {string} text
29+
* @param {string} word
30+
* @return {number}
31+
*/
32+
export default function knuthMorrisPratt(text, word) {
33+
if (word.length === 0) {
34+
return 0;
35+
}
36+
37+
let textIndex = 0;
38+
let wordIndex = 0;
39+
40+
const patternTable = buildPatternTable(word);
41+
42+
while (textIndex < text.length) {
43+
if (text[textIndex] === word[wordIndex]) {
44+
// Ta đã tìm được cái tương ứng.
45+
if (wordIndex === word.length - 1) {
46+
return (textIndex - word.length) + 1;
47+
}
48+
wordIndex += 1;
49+
textIndex += 1;
50+
} else if (wordIndex > 0) {
51+
wordIndex = patternTable[wordIndex - 1];
52+
} else {
53+
wordIndex = 0;
54+
textIndex += 1;
55+
}
56+
}
57+
58+
return -1;
59+
}

0 commit comments

Comments
 (0)