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 4141* ** String**
4242 * [ Levenshtein Distance] ( https://github.com/trekhleb/javascript-algorithms/tree/master/src/algorithms/string/levenshtein-distance ) - minimum edit distance between two sequences
4343 * [ 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
4546 * Longest common subsequence
4647 * longest common substring
47- * Rabin Karp
4848* ** Search**
4949 * [ Binary Search] ( https://github.com/trekhleb/javascript-algorithms/tree/master/src/algorithms/search/binary-search )
5050* ** 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