TheAlgorithms/C++
1.0.0
All the algorithms implemented in C++
Toggle main menu visibility
Loading...
Searching...
No Matches
manacher_algorithm.cpp
Go to the documentation of this file.
1
12
13
#include <cassert>
14
#include <cstdint>
15
#include <iostream>
16
#include <vector>
17
#ifdef _MSC_VER
18
#include <string>
19
#else
20
#include <cstring>
21
#endif
22
27
namespace
strings
{
34
namespace
manacher
{
41
std::string
manacher
(
const
std::string &prototype) {
42
if
(prototype.size() > 0) {
43
// stuffing characters between the input string to handle cases with
44
// even length palindrome
45
std::string stuffed_string =
""
;
46
for
(
auto
str : prototype) {
47
stuffed_string += str;
48
stuffed_string +=
"#"
;
49
}
50
stuffed_string =
"@#"
+ stuffed_string +
"&"
;
51
52
std::vector<uint64_t> palindrome_max_half_length(
53
stuffed_string.size(),
54
0);
// this array will consist of largest possible half length of
55
// palindrome centered at index (say i with respect to the
56
// stuffed string). This value will be lower bound of half
57
// length since single character is a palindrome in itself.
58
59
uint64_t bigger_center =
60
0;
// this is the index of the center of palindromic
61
// substring which would be considered as the larger
62
// palindrome, having symmetric halves
63
64
uint64_t right = 0;
// this is the maximum length of the palindrome
65
// from 'bigger_center' to the rightmost end
66
67
// i is considered as center lying within one half of the palindrone
68
// which is centered at 'bigger_center'
69
for
(uint64_t i = 1; i < stuffed_string.size() - 1; i++) {
70
if
(i < right) {
// when i is before right end, considering
71
// 'bigger_center' as center of palindrome
72
uint64_t opposite_to_i =
73
2 * bigger_center -
74
i;
// this is the opposite end of string, if
75
// centered at center, and having one end as i
76
77
// finding the minimum possible half length among
78
// the palindrome on having center at opposite end,
79
// and the string between i and right end,
80
// considering 'bigger_center' as center of palindrome
81
palindrome_max_half_length[i] = std::min(
82
palindrome_max_half_length[opposite_to_i], right - i);
83
}
84
85
// expanding the palindrome across the maximum stored length in the
86
// array, centered at i
87
while
(stuffed_string[i + (palindrome_max_half_length[i] + 1)] ==
88
stuffed_string[i - (palindrome_max_half_length[i] + 1)]) {
89
palindrome_max_half_length[i]++;
90
}
91
92
// if palindrome centered at i exceeds the rightmost end of
93
// palindrome centered at 'bigger_center', then i will be made the
94
// 'bigger_center' and right value will also be updated with respect
95
// to center i
96
if
(i + palindrome_max_half_length[i] > right) {
97
bigger_center = i;
98
right = i + palindrome_max_half_length[i];
99
}
100
}
101
102
// now extracting the first largest palindrome
103
uint64_t half_length = 0;
// half length of the largest palindrome
104
uint64_t center_index = 0;
// index of center of the largest palindrome
105
106
for
(uint64_t i = 1; i < stuffed_string.size() - 1; i++) {
107
if
(palindrome_max_half_length[i] > half_length) {
108
half_length = palindrome_max_half_length[i];
109
center_index = i;
110
}
111
}
112
113
std::string palindromic_substring =
114
""
;
// contains the resulting largest palindrome
115
116
if
(half_length > 0) {
117
// extra information: when '#' is the center, then palindromic
118
// substring will have even length, else palindromic substring will
119
// have odd length
120
121
uint64_t start =
122
center_index - half_length +
123
1;
// index of first character of palindromic substring
124
uint64_t end =
125
center_index + half_length -
126
1;
// index of last character of palindromic substring
127
for
(uint64_t index = start; index <= end; index += 2) {
128
palindromic_substring += stuffed_string[index];
129
}
130
}
else
{
131
// if length = 0, then there does not exist any palindrome of length
132
// > 1 so we can assign any character of length 1 from string as the
133
// palindromic substring
134
palindromic_substring = prototype[0];
135
}
136
return
palindromic_substring;
137
138
}
else
{
139
// handling case when string is empty
140
return
""
;
141
}
142
}
143
144
}
// namespace manacher
145
}
// namespace strings
146
151
static
void
test
() {
152
assert(
strings::manacher::manacher
(
""
) ==
""
);
153
assert(
strings::manacher::manacher
(
"abababc"
) ==
"ababa"
);
154
assert(
strings::manacher::manacher
(
"cbaabd"
) ==
"baab"
);
155
assert(
strings::manacher::manacher
(
"DedzefDeD"
) ==
"DeD"
);
156
assert(
strings::manacher::manacher
(
"XZYYXXYZXX"
) ==
"YXXY"
);
157
assert(
strings::manacher::manacher
(
"1sm222m10abc"
) ==
"m222m"
);
158
assert(
strings::manacher::manacher
(
"798989591"
) ==
"98989"
);
159
assert(
strings::manacher::manacher
(
"xacdedcax"
) ==
"xacdedcax"
);
160
assert(
strings::manacher::manacher
(
"xaccax"
) ==
"xaccax"
);
161
assert(
strings::manacher::manacher
(
"a"
) ==
"a"
);
162
assert(
strings::manacher::manacher
(
"xy"
) ==
"x"
);
163
assert(
strings::manacher::manacher
(
"abced"
) ==
"a"
);
164
165
std::cout <<
"All tests have passed!"
<< std::endl;
166
}
167
172
int
main
() {
173
test
();
// run self-test implementations
174
return
0;
175
}
test
void test()
Definition
caesar_cipher.cpp:100
main
int main()
Main function.
Definition
generate_parentheses.cpp:110
strings::manacher::manacher
std::string manacher(const std::string &prototype)
A function that implements Manacher's algorithm.
Definition
manacher_algorithm.cpp:41
manacher
Functions for Manacher's Algorithm implementation.
strings
String algorithms.
Definition
boyer_moore.cpp:58
strings
manacher_algorithm.cpp
Generated by
1.18.0