|
1 | 1 | package kmp
|
2 | 2 |
|
3 |
| -import ( |
4 |
| - "fmt" |
5 |
| -) |
6 |
| - |
7 |
| -// User defined. |
8 |
| -// Set to true to read input from two command line arguments |
9 |
| -// Set to false to read input from two files "pattern.txt" and "text.txt" |
10 |
| - |
11 |
| -// const isTakingInputFromCommandLine bool = true |
12 |
| - |
13 |
| -const notFoundPosition int = -1 |
14 |
| - |
15 |
| -type Result struct { |
16 |
| - resultPosition int |
17 |
| - numberOfComparison int |
18 |
| -} |
19 |
| - |
20 |
| -// Implementation of Knuth-Morris-Pratt algorithm (Prefix based approach). |
21 |
| -// Requires either a two command line arguments separated by a single space, |
22 |
| -// or two files in the same folder: "pattern.txt" containing the string to |
23 |
| -// be searched for, "text.txt" containing the text to be searched in. |
24 |
| -// func main() { |
25 |
| -// var text string |
26 |
| -// var word string |
27 |
| - |
28 |
| -// if isTakingInputFromCommandLine { // case of command line input |
29 |
| -// args := os.Args |
30 |
| -// if len(args) <= 2 { |
31 |
| -// log.Fatal("Not enough arguments. Two string arguments separated by spaces are required!") |
32 |
| -// } |
33 |
| -// word = args[1] |
34 |
| -// text = args[2] |
35 |
| -// for i := 3; i < len(args); i++ { |
36 |
| -// text = text + " " + args[i] |
37 |
| -// } |
38 |
| -// } else { // case of file input |
39 |
| -// patFile, err := ioutil.ReadFile("../pattern.txt") |
40 |
| -// if err != nil { |
41 |
| -// log.Fatal(err) |
42 |
| -// } |
43 |
| -// textFile, err := ioutil.ReadFile("../text.txt") |
44 |
| -// if err != nil { |
45 |
| -// log.Fatal(err) |
46 |
| -// } |
47 |
| -// text = string(textFile) |
48 |
| -// word = string(patFile) |
49 |
| -// } |
| 3 | +// Kmp Function kmp performing the Knuth-Morris-Pratt algorithm. |
| 4 | +func Kmp(word, text string, patternTable []int) []int { |
| 5 | + if len(word) > len(text) { |
| 6 | + return nil |
| 7 | + } |
50 | 8 |
|
51 |
| -// if len(word) > len(text) { |
52 |
| -// log.Fatal("Pattern is longer than text!") |
53 |
| -// } |
54 |
| -// fmt.Printf("\nRunning: Knuth-Morris-Pratt algorithm.\n\n") |
55 |
| -// fmt.Printf("Search word (%d chars long): %q.\n", len(word), word) |
56 |
| -// fmt.Printf("Text (%d chars long): %q.\n\n", len(text), text) |
| 9 | + var ( |
| 10 | + i, j int |
| 11 | + matches []int |
| 12 | + ) |
| 13 | + for i+j < len(text) { |
57 | 14 |
|
58 |
| -// r := kmp(text, word) |
59 |
| -// if r.resultPosition == notFoundPosition { |
60 |
| -// fmt.Printf("\n\nWord was not found.\n%d comparisons were done.", r.numberOfComparison) |
61 |
| -// } else { |
62 |
| -// fmt.Printf("\n\nWord %q was found at position %d in %q. \n%d comparisons were done.", word, |
63 |
| -// r.resultPosition, text, r.numberOfComparison) |
64 |
| -// } |
65 |
| -// } |
| 15 | + if word[j] == text[i+j] { |
| 16 | + j++ |
| 17 | + if j == len(word) { |
| 18 | + matches = append(matches, i) |
66 | 19 |
|
67 |
| -// Kmp Function kmp performing the Knuth-Morris-Pratt algorithm. |
68 |
| -// Prints whether the word/pattern was found and on what position in the text or not. |
69 |
| -// m - current match in text, i - current character in w, c - amount of comparisons. |
70 |
| -func Kmp(text string, word string) Result { |
71 |
| - m, i, c := 0, 0, 0 |
72 |
| - t := kmpTable(word) |
73 |
| - for m+i < len(text) { |
74 |
| - fmt.Printf("\n comparing characters %c %c at positions %d %d", text[m+i], word[i], m+i, i) |
75 |
| - c++ |
76 |
| - if word[i] == text[m+i] { |
77 |
| - fmt.Printf(" - match") |
78 |
| - if i == len(word)-1 { |
79 |
| - return Result{ |
80 |
| - m, c, |
81 |
| - } |
| 20 | + i = i + j |
| 21 | + j = 0 |
82 | 22 | }
|
83 |
| - i++ |
84 | 23 | } else {
|
85 |
| - m = m + i - t[i] |
86 |
| - if t[i] > -1 { |
87 |
| - i = t[i] |
| 24 | + i = i + j - patternTable[j] |
| 25 | + if patternTable[j] > -1 { |
| 26 | + j = patternTable[j] |
88 | 27 | } else {
|
89 |
| - i = 0 |
| 28 | + j = 0 |
90 | 29 | }
|
91 | 30 | }
|
92 | 31 | }
|
93 |
| - return Result{notFoundPosition, |
94 |
| - c, |
95 |
| - } |
| 32 | + return matches |
96 | 33 | }
|
97 | 34 |
|
98 |
| -// Table building algorithm. |
99 |
| -// Takes word to be analyzed and table to be filled. |
100 |
| -func kmpTable(word string) (t []int) { |
101 |
| - t = make([]int, len(word)) |
102 |
| - pos, cnd := 2, 0 |
103 |
| - t[0], t[1] = -1, 0 |
104 |
| - for pos < len(word) { |
105 |
| - if word[pos-1] == word[cnd] { |
106 |
| - cnd++ |
107 |
| - t[pos] = cnd |
108 |
| - pos++ |
109 |
| - } else if cnd > 0 { |
110 |
| - cnd = t[cnd] |
111 |
| - } else { |
112 |
| - t[pos] = 0 |
113 |
| - pos++ |
| 35 | +// table building for kmp algorithm. |
| 36 | +func table(w string) []int { |
| 37 | + var ( |
| 38 | + t []int = []int{-1} |
| 39 | + k int |
| 40 | + ) |
| 41 | + for j := 1; j < len(w); j++ { |
| 42 | + k = j - 1 |
| 43 | + for w[0:k] != w[j-k:j] && k > 0 { |
| 44 | + k-- |
114 | 45 | }
|
| 46 | + t = append(t, k) |
115 | 47 | }
|
116 | 48 | return t
|
117 | 49 | }
|
0 commit comments