​D2. Prefix-Suffix Palindrome (Hard version)​

参考:​​Codeforces Global Round 7 — Editorial​

关键在于会利用马拉车算法求最长回文串。

// Created by CAD on 2020/5/14.
#include <bits/stdc++.h>
using namespace std;

const int maxn=1e6+5;
int d1[maxn],d2[maxn];
string manacher(string &s){
//回文串的长为 2*d1[i]-1,2*d2[i]
int n=s.size();
bool bj=0;
int ans=0;
for(int i=0,l=0,r=-1;i<n;++i){
int k=(i>r)?1:min(d1[l+r-i],r-i);
while(0<=i-k&&i+k<n&&s[i-k]==s[i+k])
k++;
if(i-k+1==0&&2*k-1>ans) ans=2*k-1,bj=0;
if(i+k==n&&2*k-1>ans) bj=1,ans=2*k-1;
d1[i]=k--;
if(i+k>r)
l=i-k,r=i+k;
}
for(int i=0,l=0,r=-1;i<n;++i){
int k=(i>r)?0:min(d2[l+r-i+1],r-i+1);
while(0<=i-k-1&&i+k<n&&s[i-k-1]==s[i+k])
k++;
if(i-k==0&&2*k>ans) bj=0,ans=2*k;
if(i+k==n&&2*k>ans) bj=1,ans=2*k;
d2[i]=k--;
if(i+k>r)
l=i-k-1,r=i+k;
}
return bj?s.substr(n-ans):s.substr(0,ans);
}

int main() {
ios::sync_with_stdio(false);
cin.tie(0);
int t;cin>>t;
while (t--){
string s;cin>>s;
string s1=s;
reverse(s1.begin(),s1.end());
int ans=0,n=s.size();
while(ans<n/2&&s[ans]==s1[ans]) ans++;
string str=s.substr(ans,n-2*ans);
cout<<s.substr(0,ans)<<manacher(str)<<s.substr(n-ans)<<"\n";
}
return 0;
}