File tree Expand file tree Collapse file tree 4 files changed +88
-2
lines changed
src/algorithms/string/knuth-morris-pratt Expand file tree Collapse file tree 4 files changed +88
-2
lines changed Original file line number Diff line number Diff line change 41
41
* ** String**
42
42
* [ Levenshtein Distance] ( https://github.com/trekhleb/javascript-algorithms/tree/master/src/algorithms/string/levenshtein-distance ) - minimum edit distance between two sequences
43
43
* [ Hamming Distance] ( https://github.com/trekhleb/javascript-algorithms/tree/master/src/algorithms/string/hamming-distance ) - number of positions at which the symbols are different
44
- * Knuth Morris Pratt
44
+ * [ Knuth–Morris–Pratt algorithm] ( https://github.com/trekhleb/javascript-algorithms/tree/master/src/algorithms/string/knuth-morris-pratt ) - substring search
45
+ * Rabin Karp
45
46
* Longest common subsequence
46
47
* longest common substring
47
- * Rabin Karp
48
48
* ** Search**
49
49
* [ Binary Search] ( https://github.com/trekhleb/javascript-algorithms/tree/master/src/algorithms/search/binary-search )
50
50
* ** Sorting**
Original file line number Diff line number Diff line change
1
+ # Knuth–Morris–Pratt Algorithm
2
+
3
+ The Knuth–Morris–Pratt string searching algorithm (or
4
+ KMP algorithm) searches for occurrences of a "word" ` W `
5
+ within a main "text string" ` T ` by employing the
6
+ observation that when a mismatch occurs, the word itself
7
+ embodies sufficient information to determine where the
8
+ next match could begin, thus bypassing re-examination
9
+ of previously matched characters.
10
+
11
+ ## Complexity
12
+
13
+ - ** Time:** ` O(|W| + |T|) ` (much faster comparing to trivial ` O(|W| * |T|) ` )
14
+ - ** Space:** ` O(|W|) `
15
+
16
+ ## References
17
+
18
+ - [ Wikipedia] ( https://en.wikipedia.org/wiki/Knuth%E2%80%93Morris%E2%80%93Pratt_algorithm )
19
+ - [ YouTube] ( https://www.youtube.com/watch?v=GTJr8OvyEVQ )
Original file line number Diff line number Diff line change
1
+ import knuthMorrisPratt from '../knuthMorrisPratt' ;
2
+
3
+ describe ( 'knuthMorrisPratt' , ( ) => {
4
+ it ( 'should find word position in given text' , ( ) => {
5
+ expect ( knuthMorrisPratt ( 'abcbcglx' , 'abca' ) ) . toBe ( - 1 ) ;
6
+ expect ( knuthMorrisPratt ( 'abcbcglx' , 'bcgl' ) ) . toBe ( 3 ) ;
7
+ expect ( knuthMorrisPratt ( 'abcxabcdabxabcdabcdabcy' , 'abcdabcy' ) ) . toBe ( 15 ) ;
8
+ expect ( knuthMorrisPratt ( 'abcxabcdabxabcdabcdabcy' , 'abcdabca' ) ) . toBe ( - 1 ) ;
9
+ expect ( knuthMorrisPratt ( 'abcxabcdabxaabcdabcabcdabcdabcy' , 'abcdabca' ) ) . toBe ( 12 ) ;
10
+ expect ( knuthMorrisPratt ( 'abcxabcdabxaabaabaaaabcdabcdabcy' , 'aabaabaaa' ) ) . toBe ( 11 ) ;
11
+ } ) ;
12
+ } ) ;
Original file line number Diff line number Diff line change
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
+ let textIndex = 0 ;
34
+ let wordIndex = 0 ;
35
+
36
+ const patternTable = buildPatternTable ( word ) ;
37
+
38
+ while ( textIndex < text . length ) {
39
+ if ( text [ textIndex ] === word [ wordIndex ] ) {
40
+ // We've found a match.
41
+ if ( wordIndex === word . length - 1 ) {
42
+ return ( textIndex - word . length ) + 1 ;
43
+ }
44
+ wordIndex += 1 ;
45
+ textIndex += 1 ;
46
+ } else if ( wordIndex > 0 ) {
47
+ wordIndex = patternTable [ wordIndex - 1 ] ;
48
+ } else {
49
+ wordIndex = 0 ;
50
+ textIndex += 1 ;
51
+ }
52
+ }
53
+
54
+ return - 1 ;
55
+ }
You can’t perform that action at this time.
0 commit comments