This documentation is automatically generated by online-judge-tools/verification-helper
View the Project on GitHub kmyk/competitive-programming-library
/**
* @return radiuses of odd palindromes
* @note O(N)
* @sa http://snuke.hatenablog.com/entry/2014/12/02/235837
*/
template <class RandomAccessIterator>
vector<int> manacher(RandomAccessIterator first, RandomAccessIterator last) {
int n = distance(first, last);
vector<int> r(n);
int i = 0, j = 0;
while (i < n) {
while (i - j >= 0 and i + j < n and first[i - j] == first[i + j]) {
++ j;
}
r[i] = j;
int k = 1;
while (i - k >= 0 and i + k < n and k + r[i - k] < j) {
r[i + k] = r[i - k];
++ k;
}
i += k;
j -= k;
}
return r;
}
vector<int> odd_palindrome_length(string const & s) {
int n = s.length();
vector<int> r = manacher(ALL(s));
vector<int> l(n);
REP (i, n) l[i - r[i] + 1] = 2 * r[i] - 1;
REP (i, n-1) chmax(l[i + 1], l[i] - 2);
return l;
}
/**
* @note s must not contain '\xff'
*/
vector<int> even_palindrome_length(string const & s) {
int n = s.length();
string t(2 * n + 1, '\xff');
REP (i, n) t[2 * i + 1] = s[i];
vector<int> r = manacher(ALL(t));
vector<int> l(n);
REP (i, n) if (r[2 * i + 2] >= 3) {
l[i - r[2 * i + 2] / 2 + 1] = r[2 * i + 2] - 1;
}
REP (i, n-1) chmax(l[i + 1], l[i] - 2);
return l;
}
unittest {
string x = "abaaababa";
vector<int> y = { 1, 2, 1, 4, 1, 2, 3, 2, 1 };
assert (manacher(ALL(x)) == y);
}
struct prepared_manacher {
vector<int> odd;
vector<int> even;
prepared_manacher(string const & s) {
int n = s.length();
string t(2 * n + 1, '\xff');
REP (i, n) t[2 * i + 1] = s[i];
odd = manacher(ALL(s));
even = manacher(ALL(t));
}
/**
* @return wheter s[l, r) is a palindrome or not
*/
bool operator () (int l, int r) const {
assert (0 <= l and l <= r and r <= odd.size());
if ((r - l) % 2 == 0) {
l *= 2;
r *= 2;
int m = (l + r) / 2;
return r - m <= even[m];
} else {
int m = (l + r) / 2;
return r - m <= odd[m];
}
}
};
#line 1 "old/palindrome.inc.cpp"
/**
* @return radiuses of odd palindromes
* @note O(N)
* @sa http://snuke.hatenablog.com/entry/2014/12/02/235837
*/
template <class RandomAccessIterator>
vector<int> manacher(RandomAccessIterator first, RandomAccessIterator last) {
int n = distance(first, last);
vector<int> r(n);
int i = 0, j = 0;
while (i < n) {
while (i - j >= 0 and i + j < n and first[i - j] == first[i + j]) {
++ j;
}
r[i] = j;
int k = 1;
while (i - k >= 0 and i + k < n and k + r[i - k] < j) {
r[i + k] = r[i - k];
++ k;
}
i += k;
j -= k;
}
return r;
}
vector<int> odd_palindrome_length(string const & s) {
int n = s.length();
vector<int> r = manacher(ALL(s));
vector<int> l(n);
REP (i, n) l[i - r[i] + 1] = 2 * r[i] - 1;
REP (i, n-1) chmax(l[i + 1], l[i] - 2);
return l;
}
/**
* @note s must not contain '\xff'
*/
vector<int> even_palindrome_length(string const & s) {
int n = s.length();
string t(2 * n + 1, '\xff');
REP (i, n) t[2 * i + 1] = s[i];
vector<int> r = manacher(ALL(t));
vector<int> l(n);
REP (i, n) if (r[2 * i + 2] >= 3) {
l[i - r[2 * i + 2] / 2 + 1] = r[2 * i + 2] - 1;
}
REP (i, n-1) chmax(l[i + 1], l[i] - 2);
return l;
}
unittest {
string x = "abaaababa";
vector<int> y = { 1, 2, 1, 4, 1, 2, 3, 2, 1 };
assert (manacher(ALL(x)) == y);
}
struct prepared_manacher {
vector<int> odd;
vector<int> even;
prepared_manacher(string const & s) {
int n = s.length();
string t(2 * n + 1, '\xff');
REP (i, n) t[2 * i + 1] = s[i];
odd = manacher(ALL(s));
even = manacher(ALL(t));
}
/**
* @return wheter s[l, r) is a palindrome or not
*/
bool operator () (int l, int r) const {
assert (0 <= l and l <= r and r <= odd.size());
if ((r - l) % 2 == 0) {
l *= 2;
r *= 2;
int m = (l + r) / 2;
return r - m <= even[m];
} else {
int m = (l + r) / 2;
return r - m <= odd[m];
}
}
};