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