@@ -17,41 +17,41 @@ runnableExamples:
17
17
doAssert (manacherLength (example1) == 5 )
18
18
19
19
func manacherIndex * (s: string ): HSlice [int , int ] {.raises : [ValueError ].} =
20
- # # Find the start and stop index for the longest palindrome in a string by Manacher
21
- # #
22
- # # :returns: indexes i and j such that s\[i:j\] is the longest palindrome in s
23
- # # :param s: string, lowercase ascii, no whitespace
24
- # # :time complexity: O(len(s))
25
- # # All the indexes refer to an intermediate string t
26
- # # of the form "^#a#b#a#a#$" for s="abaa"
27
- if s.len == 0 :
28
- raise newException (ValueError , " Empty string" )
29
- let extraSymbols = toHashSet (['$' , '^' , '#' ])
30
- let letters = toHashSet (s.toLowerAscii)
31
- assert disjoint (extraSymbols, letters) # Forbidden letters
32
- if s == " " :
33
- return 0 .. 1
34
- let s = " ^#" & join (s, " #" ) & " #$"
35
- var
36
- center = 1
37
- distance = 1
38
- p = repeat (0 , len (s)) # Palindrome radii for each index in s
39
- for index in 2 ..< len (s)- 1 :
40
- # reflect index with respect to center
41
- let mirror = 2 * center - index # = center - (index - center)
42
- p[index] = max (0 , min (distance - index, p[mirror]))
43
- # grow palindrome centered in i
44
- while s[index + 1 + p[index]] == s[index - 1 - p[index]]:
45
- p[index] += 1
46
- # adjust center if necessary
47
- if index + p[index] > distance:
48
- center = index
49
- distance = index + p[index]
50
- # find the argmax index in p
51
- var
52
- j = maxIndex (p)
53
- k = p[j]
54
- return (j - k) div 2 ..< (j + k) div 2 # extract solution
20
+ # # Find the start and stop index for the longest palindrome in a string by Manacher
21
+ # #
22
+ # # :returns: indexes i and j such that s\[i:j\] is the longest palindrome in s
23
+ # # :param s: string, lowercase ascii, no whitespace
24
+ # # :time complexity: O(len(s))
25
+ # # All the indexes refer to an intermediate string t
26
+ # # of the form "^#a#b#a#a#$" for s="abaa"
27
+ if s.len == 0 :
28
+ raise newException (ValueError , " Empty string" )
29
+ let extraSymbols = toHashSet (['$' , '^' , '#' ])
30
+ let letters = toHashSet (s.toLowerAscii)
31
+ assert disjoint (extraSymbols, letters) # Forbidden letters
32
+ if s == " " :
33
+ return 0 .. 1
34
+ let s = " ^#" & join (s, " #" ) & " #$"
35
+ var
36
+ center = 1
37
+ distance = 1
38
+ p = repeat (0 , len (s)) # Palindrome radii for each index in s
39
+ for index in 2 ..< len (s)- 1 :
40
+ # reflect index with respect to center
41
+ let mirror = 2 * center - index # = center - (index - center)
42
+ p[index] = max (0 , min (distance - index, p[mirror]))
43
+ # grow palindrome centered in i
44
+ while s[index + 1 + p[index]] == s[index - 1 - p[index]]:
45
+ p[index] += 1
46
+ # adjust center if necessary
47
+ if index + p[index] > distance:
48
+ center = index
49
+ distance = index + p[index]
50
+ # find the argmax index in p
51
+ var
52
+ j = maxIndex (p)
53
+ k = p[j]
54
+ return (j - k) div 2 ..< (j + k) div 2 # extract solution
55
55
56
56
func manacherString * (s: string ): string {.raises : [ValueError ].} =
57
57
# # Returns the longest palindrome
@@ -81,7 +81,7 @@ when isMainModule:
81
81
check manacherIndex (" telet" ) == 0 .. 4
82
82
check manacherLength (" telet" ) == 5
83
83
check manacherString (" telet" ) == " telet"
84
-
84
+
85
85
test " Empty string" :
86
86
doAssertRaises (ValueError ):
87
87
discard manacherIndex (" " )
0 commit comments