Skip to content

Commit 5775a12

Browse files
authored
Merge pull request #564 from shabirjan/Knuth-Morris-Pratt-Swift4
Knuth morris pratt Swift4
2 parents ab53bac + a6c3e9f commit 5775a12

File tree

2 files changed

+163
-158
lines changed

2 files changed

+163
-158
lines changed

Knuth-Morris-Pratt/KnuthMorrisPratt.playground/Contents.swift

+105-100
Original file line numberDiff line numberDiff line change
@@ -1,115 +1,120 @@
11
//: Playground - noun: a place where people can play
22

3+
// last checked with Xcode 9.0b4
4+
#if swift(>=4.0)
5+
print("Hello, Swift4!")
6+
#endif
7+
38
func ZetaAlgorithm(ptnr: String) -> [Int]? {
9+
10+
let pattern = Array(ptnr.characters)
11+
let patternLength: Int = pattern.count
12+
13+
guard patternLength > 0 else {
14+
return nil
15+
}
16+
17+
var zeta: [Int] = [Int](repeating: 0, count: patternLength)
18+
19+
var left: Int = 0
20+
var right: Int = 0
21+
var k_1: Int = 0
22+
var betaLength: Int = 0
23+
var textIndex: Int = 0
24+
var patternIndex: Int = 0
25+
26+
for k in 1 ..< patternLength {
27+
if k > right {
28+
patternIndex = 0
29+
30+
while k + patternIndex < patternLength &&
31+
pattern[k + patternIndex] == pattern[patternIndex] {
32+
patternIndex = patternIndex + 1
33+
}
34+
35+
zeta[k] = patternIndex
36+
37+
if zeta[k] > 0 {
38+
left = k
39+
right = k + zeta[k] - 1
40+
}
41+
} else {
42+
k_1 = k - left + 1
43+
betaLength = right - k + 1
44+
45+
if zeta[k_1 - 1] < betaLength {
46+
zeta[k] = zeta[k_1 - 1]
47+
} else if zeta[k_1 - 1] >= betaLength {
48+
textIndex = betaLength
49+
patternIndex = right + 1
50+
51+
while patternIndex < patternLength && pattern[textIndex] == pattern[patternIndex] {
52+
textIndex = textIndex + 1
53+
patternIndex = patternIndex + 1
54+
}
55+
zeta[k] = patternIndex - k
56+
left = k
57+
right = patternIndex - 1
58+
}
59+
}
60+
}
61+
return zeta
62+
}
463

64+
extension String {
65+
66+
func indexesOf(ptnr: String) -> [Int]? {
67+
68+
let text = Array(self.characters)
569
let pattern = Array(ptnr.characters)
70+
71+
let textLength: Int = text.count
672
let patternLength: Int = pattern.count
7-
73+
874
guard patternLength > 0 else {
9-
return nil
75+
return nil
1076
}
11-
12-
var zeta: [Int] = [Int](repeating: 0, count: patternLength)
13-
14-
var left: Int = 0
15-
var right: Int = 0
16-
var k_1: Int = 0
17-
var betaLength: Int = 0
77+
78+
var suffixPrefix: [Int] = [Int](repeating: 0, count: patternLength)
1879
var textIndex: Int = 0
1980
var patternIndex: Int = 0
20-
21-
for k in 1 ..< patternLength {
22-
if k > right {
23-
patternIndex = 0
24-
25-
while k + patternIndex < patternLength &&
26-
pattern[k + patternIndex] == pattern[patternIndex] {
27-
patternIndex = patternIndex + 1
28-
}
29-
30-
zeta[k] = patternIndex
31-
32-
if zeta[k] > 0 {
33-
left = k
34-
right = k + zeta[k] - 1
35-
}
36-
} else {
37-
k_1 = k - left + 1
38-
betaLength = right - k + 1
39-
40-
if zeta[k_1 - 1] < betaLength {
41-
zeta[k] = zeta[k_1 - 1]
42-
} else if zeta[k_1 - 1] >= betaLength {
43-
textIndex = betaLength
44-
patternIndex = right + 1
45-
46-
while patternIndex < patternLength && pattern[textIndex] == pattern[patternIndex] {
47-
textIndex = textIndex + 1
48-
patternIndex = patternIndex + 1
49-
}
50-
zeta[k] = patternIndex - k
51-
left = k
52-
right = patternIndex - 1
53-
}
54-
}
81+
var indexes: [Int] = [Int]()
82+
83+
/* Pre-processing stage: computing the table for the shifts (through Z-Algorithm) */
84+
let zeta = ZetaAlgorithm(ptnr: ptnr)
85+
86+
for patternIndex in (1 ..< patternLength).reversed() {
87+
textIndex = patternIndex + zeta![patternIndex] - 1
88+
suffixPrefix[textIndex] = zeta![patternIndex]
5589
}
56-
return zeta
57-
}
58-
59-
extension String {
60-
61-
func indexesOf(ptnr: String) -> [Int]? {
62-
63-
let text = Array(self.characters)
64-
let pattern = Array(ptnr.characters)
65-
66-
let textLength: Int = text.count
67-
let patternLength: Int = pattern.count
68-
69-
guard patternLength > 0 else {
70-
return nil
71-
}
72-
73-
var suffixPrefix: [Int] = [Int](repeating: 0, count: patternLength)
74-
var textIndex: Int = 0
75-
var patternIndex: Int = 0
76-
var indexes: [Int] = [Int]()
77-
78-
/* Pre-processing stage: computing the table for the shifts (through Z-Algorithm) */
79-
let zeta = ZetaAlgorithm(ptnr: ptnr)
80-
81-
for patternIndex in (1 ..< patternLength).reversed() {
82-
textIndex = patternIndex + zeta![patternIndex] - 1
83-
suffixPrefix[textIndex] = zeta![patternIndex]
84-
}
85-
86-
/* Search stage: scanning the text for pattern matching */
87-
textIndex = 0
88-
patternIndex = 0
89-
90-
while textIndex + (patternLength - patternIndex - 1) < textLength {
91-
92-
while patternIndex < patternLength && text[textIndex] == pattern[patternIndex] {
93-
textIndex = textIndex + 1
94-
patternIndex = patternIndex + 1
95-
}
96-
97-
if patternIndex == patternLength {
98-
indexes.append(textIndex - patternIndex)
99-
}
100-
101-
if patternIndex == 0 {
102-
textIndex = textIndex + 1
103-
} else {
104-
patternIndex = suffixPrefix[patternIndex - 1]
105-
}
106-
}
107-
108-
guard !indexes.isEmpty else {
109-
return nil
110-
}
111-
return indexes
90+
91+
/* Search stage: scanning the text for pattern matching */
92+
textIndex = 0
93+
patternIndex = 0
94+
95+
while textIndex + (patternLength - patternIndex - 1) < textLength {
96+
97+
while patternIndex < patternLength && text[textIndex] == pattern[patternIndex] {
98+
textIndex = textIndex + 1
99+
patternIndex = patternIndex + 1
100+
}
101+
102+
if patternIndex == patternLength {
103+
indexes.append(textIndex - patternIndex)
104+
}
105+
106+
if patternIndex == 0 {
107+
textIndex = textIndex + 1
108+
} else {
109+
patternIndex = suffixPrefix[patternIndex - 1]
110+
}
111+
}
112+
113+
guard !indexes.isEmpty else {
114+
return nil
112115
}
116+
return indexes
117+
}
113118
}
114119

115120
/* Examples */
+58-58
Original file line numberDiff line numberDiff line change
@@ -1,65 +1,65 @@
11
/* Knuth-Morris-Pratt algorithm for pattern/string matching
2-
3-
The code is based on the book:
4-
"Algorithms on String, Trees and Sequences: Computer Science and Computational Biology"
5-
by Dan Gusfield
6-
Cambridge University Press, 1997
7-
*/
2+
3+
The code is based on the book:
4+
"Algorithms on String, Trees and Sequences: Computer Science and Computational Biology"
5+
by Dan Gusfield
6+
Cambridge University Press, 1997
7+
*/
88

99
import Foundation
1010

1111
extension String {
12-
13-
func indexesOf(ptnr: String) -> [Int]? {
14-
15-
let text = Array(self.characters)
16-
let pattern = Array(ptnr.characters)
17-
18-
let textLength: Int = text.count
19-
let patternLength: Int = pattern.count
20-
21-
guard patternLength > 0 else {
22-
return nil
23-
}
24-
25-
var suffixPrefix: [Int] = [Int](repeating: 0, count: patternLength)
26-
var textIndex: Int = 0
27-
var patternIndex: Int = 0
28-
var indexes: [Int] = [Int]()
29-
30-
/* Pre-processing stage: computing the table for the shifts (through Z-Algorithm) */
31-
let zeta = ZetaAlgorithm(ptnr: ptnr)
32-
33-
for patternIndex in (1 ..< patternLength).reversed() {
34-
textIndex = patternIndex + zeta![patternIndex] - 1
35-
suffixPrefix[textIndex] = zeta![patternIndex]
36-
}
37-
38-
/* Search stage: scanning the text for pattern matching */
39-
textIndex = 0
40-
patternIndex = 0
41-
42-
while textIndex + (patternLength - patternIndex - 1) < textLength {
43-
44-
while patternIndex < patternLength && text[textIndex] == pattern[patternIndex] {
45-
textIndex = textIndex + 1
46-
patternIndex = patternIndex + 1
47-
}
48-
49-
if patternIndex == patternLength {
50-
indexes.append(textIndex - patternIndex)
51-
}
52-
53-
if patternIndex == 0 {
54-
textIndex = textIndex + 1
55-
} else {
56-
patternIndex = suffixPrefix[patternIndex - 1]
57-
}
58-
}
59-
60-
guard !indexes.isEmpty else {
61-
return nil
62-
}
63-
return indexes
12+
13+
func indexesOf(ptnr: String) -> [Int]? {
14+
15+
let text = Array(self.characters)
16+
let pattern = Array(ptnr.characters)
17+
18+
let textLength: Int = text.count
19+
let patternLength: Int = pattern.count
20+
21+
guard patternLength > 0 else {
22+
return nil
23+
}
24+
25+
var suffixPrefix: [Int] = [Int](repeating: 0, count: patternLength)
26+
var textIndex: Int = 0
27+
var patternIndex: Int = 0
28+
var indexes: [Int] = [Int]()
29+
30+
/* Pre-processing stage: computing the table for the shifts (through Z-Algorithm) */
31+
let zeta = ZetaAlgorithm(ptnr: ptnr)
32+
33+
for patternIndex in (1 ..< patternLength).reversed() {
34+
textIndex = patternIndex + zeta![patternIndex] - 1
35+
suffixPrefix[textIndex] = zeta![patternIndex]
36+
}
37+
38+
/* Search stage: scanning the text for pattern matching */
39+
textIndex = 0
40+
patternIndex = 0
41+
42+
while textIndex + (patternLength - patternIndex - 1) < textLength {
43+
44+
while patternIndex < patternLength && text[textIndex] == pattern[patternIndex] {
45+
textIndex = textIndex + 1
46+
patternIndex = patternIndex + 1
47+
}
48+
49+
if patternIndex == patternLength {
50+
indexes.append(textIndex - patternIndex)
51+
}
52+
53+
if patternIndex == 0 {
54+
textIndex = textIndex + 1
55+
} else {
56+
patternIndex = suffixPrefix[patternIndex - 1]
57+
}
58+
}
59+
60+
guard !indexes.isEmpty else {
61+
return nil
6462
}
63+
return indexes
64+
}
6565
}

0 commit comments

Comments
 (0)