#include<bits/stdc++.h>
using namespace std;
int P[200001]; // Longest Palidrome centered around position i
int S[200001]; // Longest Palidrome that starts at position i "lower bound of the radius"
int E[200001]; // Longest Palidrome that ends at position i "upper bound of the radius"
int Pr[200001];
int N;
int n;
string s;
void manacher()
{
N = 2*n + 1;
P[0] = 0;
E[0] = 0;
int center = 0;
int centerRight = 0;
int i;
int maxLPSLength = 0;
int maxLPSCenterPosition = 0;
int distToEdge;
for (i = 1; i < N; i++)
{
P[i] = 0;
distToEdge = centerRight - i;
if(distToEdge > 0) {
P[i] = min(P[center*2-i], distToEdge);
if(i-P[i] <= N/2)
S[ i-P[i] ] = max(S[ i-P[i] ], P[i]);
if(i+P[i] >= N/2)
E[ i+P[i] ] = max(E[ i+P[i] ], P[i]);
}
while
(
(i + P[i] < N - 1) && (i - P[i] > 0) &&
(
( (i + P[i])&1 ) ||
( s[(i+P[i])/2]==s[(i-P[i]-1)/2] )
)
)
{
P[i]++;
if(i-P[i] <= N/2)
S[ i-P[i] ] = max(S[ i-P[i] ], P[i]);
if(i+P[i] >= N/2)
E[ i+P[i] ] = max(E[ i+P[i] ], P[i]);
}
if(P[i] > maxLPSLength) {
maxLPSLength = P[i];
maxLPSCenterPosition = i;
}
if (i + P[i] > centerRight) {
center = i;
centerRight = i + P[i];
}
}
Pr[N-1] = 0;
S[N-1] = 0;
center = N-1;
int centerLeft = N-1;
for (i = N-2; i >= 0; i--)
{
Pr[i] = 0;
distToEdge = i - centerLeft;
if(distToEdge > 0) {
Pr[i] = min(Pr[center*2-i], distToEdge);
if(i-Pr[i] > N/2)
S[ i-Pr[i] ] = max(S[ i-Pr[i] ], Pr[i]);
if(i+Pr[i] < N/2)
E[ i+Pr[i] ] = max(E[ i+Pr[i] ], Pr[i]);
}
while
(
(i - Pr[i] > 0) && (i + Pr[i] < N - 1) &&
(
( (i - Pr[i])&1 ) ||
( s[(i-Pr[i]-1)/2]==s[(i+Pr[i])/2] )
)
)
{
Pr[i]++;
if(i-Pr[i] > N/2)
S[ i-Pr[i] ] = max(S[ i-Pr[i] ], Pr[i]);
if(i+Pr[i] < N/2)
E[ i+Pr[i] ] = max(E[ i+Pr[i] ], Pr[i]);
}
if (i - Pr[i] > centerLeft) {
center = i;
centerLeft = i + Pr[i];
}
}
int start = (maxLPSCenterPosition - maxLPSLength)/2;
cout << "String: " << s << '\n';
cout << "MString: #"; for(int i = 0; i < s.length(); i++) cout << s[i] << '#'; cout << '\n';
cout << "The Longest Palindromic Substring: " << s.substr(start, maxLPSLength) << '\n';
}
int main() {
ios_base::sync_with_stdio(false); cin.tie(NULL);
s = "cbcbaaabc";
n = s.length();
manacher();
cout << "The Longest Palindrome Length Starting at Every Index:\n";
for(int i = 0; i < n; i++)
cout << max(S[i*2], S[i*2+1]) << ' ';
cout << '\n';
cout << "The Longest Palindrome Length Ending at Every Index:\n";
for(int i = 0; i < n; i++)
cout << max(E[i*2+1], E[i*2+2]) << ' ';
cout << "\n\n";
memset(P, 0, sizeof(P));
memset(Pr, 0, sizeof(Pr));
memset(S, 0, sizeof(S));
memset(E, 0, sizeof(E));
s = "cbcbbcc";
n = s.length();
manacher();
cout << "The Longest Palindrome Length Starting at Every Index:\n";
for(int i = 0; i < n; i++)
cout << max(S[i*2], S[i*2+1]) << ' ';
cout << '\n';
cout << "The Longest Palindrome Length Ending at Every Index:\n";
for(int i = 0; i < n; i++)
cout << max(E[i*2+1], E[i*2+2]) << ' ';
cout << "\n\n";
memset(P, 0, sizeof(P));
memset(Pr, 0, sizeof(Pr));
memset(S, 0, sizeof(S));
memset(E, 0, sizeof(E));
s = "dcbcbbcccbbcbc";
n = s.length();
manacher();
cout << "The Longest Palindrome Length Starting at Every Index:\n";
for(int i = 0; i < n; i++)
cout << max(S[i*2], S[i*2+1]) << ' ';
cout << '\n';
cout << "The Longest Palindrome Length Ending at Every Index:\n";
for(int i = 0; i < n; i++)
cout << max(E[i*2+1], E[i*2+2]) << ' ';
cout << "\n\n";
return 0;
}