题目链接
思路:不知道为什么比赛的时候作死哈希,最后还被fst了呜呜呜。
其实比赛的时候也想到了马拉车,但马拉车的题没怎么练过,有点生手,马拉车里p【i】表示的是i这个位置的回文半径,那么要找它的最长回文前缀的话就判断一下i-p【i】是否等于0,i+p【i】是否能到达字符串尾就行了,相当的简单。
#include<bits/stdc++.h>
using namespace std;
const int maxn=1e6+1;
char s[maxn];
void Manacher(string s) {
string t = "$#";
for (int i = 0; i < s.size(); ++i) {
t += s[i];
t += "#";
}
vector<int> p(t.size(), 0);
int mx = 0, id = 0, resLen = 0, resCenter = 0;
for (int i = 1; i < t.size(); ++i) {
p[i] = mx > i ? min(p[2 * id - i], mx - i) : 1;
while (t[i + p[i]] == t[i - p[i]]) ++p[i];
if (mx < i + p[i]) {
mx = i + p[i];
id = i;
}
if(i-p[i]<=0||i+p[i]-1>=t.size()-1)
if (resLen < p[i]) {
resLen = p[i];
resCenter = i;
}
}
for(int i=resCenter-resLen+1;i<=resCenter+resLen-1;++i)
if(t[i]>='a'&&t[i]<='z') cout<<t[i];
}
int main() {
int T;
scanf("%d",&T);
while(T--)
{
string str,str1;
scanf("%s",s+1);
int left=1,len=strlen(s+1);
while(left<=(len/2)&&s[left]==s[len-left+1]) str+=s[left++];
cout<<str;
for(int i=left;i<=len-left+1;++i) str1+=s[i];
Manacher(str1);
for(int i=left-1;i>=1;--i) printf("%c",s[i]);
printf("\n");
}
}