On this page
article
Manacher
Sobre
manacher recebe um vetor de T e retorna o vetor com tamanho dos palindromos
ret[2*i] = tamanho do maior palindromo centrado em i
ret[2*i+1] = tamanho maior palindromo centrado em i e i+1
Complexidades:
manacher - O(n)
palindrome - <O(n), O(1)>
pal_end - O(n)
Link original: manacher.cpp
Código
template<typename T> vector<int> manacher(const T& s) {
int l = 0, r = -1, n = s.size();
vector<int> d1(n), d2(n);
for (int i = 0; i < n; i++) {
int k = i > r ? 1 : min(d1[l+r-i], r-i);
while (i+k < n && i-k >= 0 && s[i+k] == s[i-k]) k++;
d1[i] = k--;
if (i+k > r) l = i-k, r = i+k;
}
l = 0, r = -1;
for (int i = 0; i < n; i++) {
int k = i > r ? 0 : min(d2[l+r-i+1], r-i+1); k++;
while (i+k <= n && i-k >= 0 && s[i+k-1] == s[i-k]) k++;
d2[i] = --k;
if (i+k-1 > r) l = i-k, r = i+k-1;
}
vector<int> ret(2*n-1);
for (int i = 0; i < n; i++) ret[2*i] = 2*d1[i]-1;
for (int i = 0; i < n-1; i++) ret[2*i+1] = 2*d2[i+1];
return ret;
}
// verifica se a string s[i..j] eh palindromo
template<typename T> struct palindrome {
vector<int> man;
palindrome(const T& s) : man(manacher(s)) {}
bool query(int i, int j) {
return man[i+j] >= j-i+1;
}
};
// tamanho do maior palindromo que termina em cada posicao
template<typename T> vector<int> pal_end(const T& s) {
vector<int> ret(s.size());
palindrome<T> p(s);
ret[0] = 1;
for (int i = 1; i < s.size(); i++) {
ret[i] = min(ret[i-1]+2, i+1);
while (!p.query(i-ret[i]+1, i)) ret[i]--;
}
return ret;
}