UVA11475 Extend to Palindrome 题解
题目链接:UVA11475 Extend to Palindrome
题意:
输入多个字符串。
对于每个字符串 $S^{}$ ,求出一个字符串$S^{}$, $S^{*}$ 需要满足:
- $S^$为 $S^{}$ 的前缀;
- $S^*$ 是一个回文字符串;
- $|S^{*}|$应尽可能小;
对于每个 $S$ ,输出 $S^{*}$ ,每行输出以换行符结尾。
可以发现我们似乎要从原字符串中找到一个最长的回文串
然后以该回文串的中心为对称轴对称过去
如amanaplanacanal
要变换成amanaplanacanalpanama
但是还有一个问题,比如下面这个例子
axxxxxxxxxxxxxxdyyy
由于 $S$ 为 $S^{}$ 的前缀,所以我们要找的是*最长的后缀回文串
使用Manacher算法即可
代码如下
#include <bits/stdc++.h>
using namespace std;
#define int long long
#define MAXN (int)(1e5+5)
char a[MAXN<<1],s[MAXN];
int x,mx,n,m,p[MAXN<<1],mid=1,r=1;
void init()
{
mx=1;mid=1;r=1;
memset(p,0,(m+1)*sizeof(int));
}
signed main()
{
while(~scanf("%s",s+1))
{
n=strlen(s+1);a[0]='$';
for(int i=1; i<=n; i++)
a[i*2-1]='#',a[i*2]=s[i];
m=strlen(a+1);
a[++m]='#';
init();
for(int i=1; i<=m; i++)
{
if(i<=r)p[i]=min(p[(mid<<1)-i],r-i+1);
while(a[i-p[i]]==a[i+p[i]])++p[i];
if(i+p[i]-1>=r)r=i+p[i]-1,mid=i;
if(i/2+(p[i]-1)/2==n)mx=max(mx,p[i]-1);
}
printf("%s",s+1);
for(int i=n-mx; i>=1; i--)
putchar(s[i]);
puts("");
}
return 0;
}