D2 - Prefix-Suffix Palindrome (Hard version)
題意
思路
若s串首尾字符相同,那麼我們可以直接去除不影響答案。
故先從兩邊取對稱的前後綴,之後再取餘下字符串較長的迴文前綴或後綴。
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef pair<int,int>P;
const double eps = 1e-8;
const int NINF = 0xc0c0c0c0;
const int INF = 0x3f3f3f3f;
const ll mod = 1e9 + 7;
const ll maxn = 3e6 + 5;
char s[maxn],a[maxn],b[maxn];
int p[maxn];
int ansid;
void manacher(int n){
int m=0,mx=0,id=0;
s[++m]='$';
s[++m]='#';
for(int i=1;i<=n;i++){
s[++m]=a[i];
s[++m]='#';
}
s[++m]='%';
ansid=0;
for(int i=3;i<m;i++){
p[i]=mx>i?min(p[id*2-i],mx-i):1;
while(s[i+p[i]]==s[i-p[i]]) ++p[i];
if(i+p[i]>mx) mx=i+p[i],id=i;
if(i+p[i]-1>=2*n+1 || i-p[i]+1<=3){//如果爲前綴和後綴那邊所在的最大回文串則記錄ansid以便於後續輸出
if(p[i]>p[ansid]) ansid=i;
}
}
for(int i=ansid-p[ansid]+1;i<=ansid+p[ansid]-1;i++){
if(isalpha(s[i])) cout<<s[i];
}
}
int main(){
ios::sync_with_stdio(false);
cin.tie(0);
int T;cin>>T;
while(T--){
cin>>b+1;
int L=1,R=strlen(b+1),len=0;
while(len+1<=R/2 && b[L+len]==b[R-len]) len++;
for(int i=1;i<=len;i++) cout<<b[i];
int cnt=0;
for(int i=len+1;i<=R-len;i++) a[++cnt]=b[i];
manacher(cnt);
for(int i=len;i>=1;i--) cout<<b[i];cout<<'\n';
}
return 0;
}