forked from TheAlgorithms/Go
-
Notifications
You must be signed in to change notification settings - Fork 0
/
bom.go
228 lines (216 loc) · 7.43 KB
/
bom.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
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
package bom
// User defined.
// Set to true to print various extra stuff out (slows down the execution)
// Set to false for quick and quiet execution.
// const debugMode bool = false
// 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 commandLineInput bool = false
// Implementation of Backward Oracle Matching algorithm (Factor 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() {
// if commandLineInput == true { // 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!")
// }
// pattern := args[1]
// s := args[2]
// for i := 3; i < len(args); i++ {
// s = s + " " + args[i]
// }
// if len(args[1]) > len(s) {
// log.Fatal("Pattern is longer than text!")
// }
// if debugMode == true {
// fmt.Printf("\nRunning: Backward Oracle Matching algorithm.\n\n")
// fmt.Printf("Search word (%d chars long): %q.\n", len(args[1]), pattern)
// fmt.Printf("Text (%d chars long): %q.\n\n", len(s), s)
// } else {
// fmt.Printf("\nRunning: Backward Oracle Matching algorithm.\n\n")
// }
// bom(s, pattern)
// } else if commandLineInput == false { // case of file line 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)
// }
// if len(patFile) > len(textFile) {
// log.Fatal("Pattern is longer than text!")
// }
// if debugMode == true {
// fmt.Printf("\nRunning: Backward Oracle Matching alghoritm.\n\n")
// fmt.Printf("Search word (%d chars long): %q.\n", len(patFile), patFile)
// fmt.Printf("Text (%d chars long): %q.\n\n", len(textFile), textFile)
// } else {
// fmt.Printf("\nRunning: Backward Oracle Matching alghoritm.\n\n")
// }
// bom(string(textFile), string(patFile))
// }
// }
// // Function bom performing the Backward Oracle Matching algorithm.
// // Prints whether the word/pattern was found + positions of possible multiple occurrences
// // or that the word was not found.
// func bom(t, p string) {
// startTime := time.Now()
// n, m := len(t), len(p)
// var current, j, pos int
// oracle := oracleOnLine(reverse(p))
// occurrences := make([]int, len(t))
// currentOcc := 0
// pos = 0
// if debugMode == true {
// fmt.Printf("\n\nWe are reading backwards in %q, searching for %q\n\nat position %d:\n", t, p, pos+m-1)
// }
// for pos <= n-m {
// current = 0 //initial state of the oracle
// j = m
// for j > 0 && stateExists(current, oracle) {
// if debugMode == true {
// prettyPrint(current, j, n, pos, t, oracle)
// }
// current = getTransition(current, t[pos+j-1], oracle)
// j--
// }
// if stateExists(current, oracle) {
// if debugMode == true {
// fmt.Printf(" We got an occurrence!")
// }
// occurrences[currentOcc] = pos
// currentOcc++
// }
// pos = pos + j + 1
// if pos+m-1 < len(t) {
// if debugMode == true {
// fmt.Printf("\n\nposition %d:\n", pos+m-1)
// }
// }
// }
// elapsed := time.Since(startTime)
// fmt.Printf("\n\nElapsed %f secs\n", elapsed.Seconds())
// fmt.Printf("\n\n")
// if currentOcc > 0 {
// fmt.Printf("Word %q was found %d times at positions: ", p, currentOcc)
// for k := 0; k < currentOcc-1; k++ {
// fmt.Printf("%d, ", occurrences[k])
// }
// fmt.Printf("%d", occurrences[currentOcc-1])
// fmt.Printf(".\n")
// }
// if currentOcc == 0 {
// fmt.Printf("\nWord was not found.\n")
// }
// return
// }
// // Construction of the factor oracle automaton for a word p.
// func oracleOnLine(p string) (oracle map[int]map[uint8]int) {
// if debugMode == true {
// fmt.Printf("Oracle construction: \n")
// }
// oracle = make(map[int]map[uint8]int)
// supply := make([]int, len(p)+2) // supply function
// createNewState(0, oracle)
// supply[0] = -1
// var orP string
// for j := 0; j < len(p); j++ {
// oracle, orP = oracleAddLetter(oracle, supply, orP, p[j])
// }
// return oracle
// }
// // Adds one letter to the oracle.
// func oracleAddLetter(oracle map[int]map[uint8]int, supply []int, orP string, o uint8) (oracleToReturn map[int]map[uint8]int, orPToReturn string) {
// m := len(orP)
// var s int
// createNewState(m+1, oracle)
// createTransition(m, o, m+1, oracle)
// k := supply[m]
// for k > -1 && getTransition(k, o, oracle) == -1 {
// createTransition(k, o, m+1, oracle)
// k = supply[k]
// }
// if k == -1 {
// s = 0
// } else {
// s = getTransition(k, o, oracle)
// }
// supply[m+1] = s
// return oracle, orP + string(o)
// }
// // Function that takes a single string and reverses it.
// // @author 'Walter' http://stackoverflow.com/a/10043083
// func reverse(s string) string {
// l := len(s)
// m := make([]rune, l)
// for _, c := range s {
// l--
// m[l] = c
// }
// return string(m)
// }
// // Automaton function for creating a new state.
// func createNewState(state int, at map[int]map[uint8]int) {
// at[state] = make(map[uint8]int)
// if debugMode == true {
// fmt.Printf("\ncreated state %d", state)
// }
// }
// // Creates a transition for function σ(state,letter) = end.
// func createTransition(fromState int, overChar uint8, toState int, at map[int]map[uint8]int) {
// at[fromState][overChar] = toState
// if debugMode == true {
// fmt.Printf("\n σ(%d,%c)=%d;", fromState, overChar, toState)
// }
// }
// // Returns ending state for transition σ(fromState,overChar), -1 if there is none.
// func getTransition(fromState int, overChar uint8, at map[int]map[uint8]int) (toState int) {
// if !stateExists(fromState, at) {
// return -1
// }
// toState, ok := at[fromState][overChar]
// if ok == false {
// return -1
// }
// return toState
// }
// // Checks if state exists. Returns true if it does, false otherwise.
// func stateExists(state int, at map[int]map[uint8]int) bool {
// _, ok := at[state]
// if !ok || state == -1 || at[state] == nil {
// return false
// }
// return true
// }
// // Just some printing of extra information about what the algorithm does.
// func prettyPrint(current int, j int, n int, pos int, t string, oracle map[int]map[uint8]int) {
// if current == 0 && !(getTransition(current, t[pos+j-1], oracle) == -1) {
// fmt.Printf("\n -->(%d)---(%c)--->(%d)", current, t[pos+j-1], getTransition(current, t[pos+j-1], oracle))
// } else if getTransition(current, t[pos+j-1], oracle) == -1 && current != 0 {
// fmt.Printf("\n (%d)---(%c) ", current, t[pos+j-1])
// } else if getTransition(current, t[pos+j-1], oracle) == -1 && current == 0 {
// fmt.Printf("\n -->(%d)---(%c) ", current, t[pos+j-1])
// } else {
// fmt.Printf("\n (%d)---(%c)--->(%d)", current, t[pos+j-1], getTransition(current, t[pos+j-1], oracle))
// }
// fmt.Printf(" ")
// for a := 0; a < pos+j-1; a++ {
// fmt.Printf("%c", t[a])
// }
// if getTransition(current, t[pos+j-1], oracle) == -1 {
// fmt.Printf("[%c]", t[pos+j-1])
// } else {
// fmt.Printf("[%c]", t[pos+j-1])
// }
// for a := pos + j; a < n; a++ {
// fmt.Printf("%c", t[a])
// }
// if getTransition(current, t[pos+j-1], oracle) == -1 {
// fmt.Printf(" FAIL on the character[%c]", t[pos+j-1])
// }
// }