题目链接:UVA11475 Extend to Palindrome
题意:
输入多个字符串。
对于每个字符串 S ∗ S^* S∗ ,求出一个字符串 S ∗ S^* S∗, S ∗ S^* S∗ 需要满足:
S ∗ S^* S∗为 S ∗ S^* S∗ 的前缀; S ∗ S^* S∗ 是一个回文字符串; ∣ S ∗ ∣ |S^*| ∣S∗∣应尽可能小;
对于每个 S S S ,输出 S ∗ S^* S∗ ,每行输出以换行符结尾。
震惊!q779竟然把原题抄下来了!有史以来第一次!
可以发现我们似乎要从原字符串中找到一个最长的回文串
然后以该回文串的中心为对称轴对称过去
如amanaplanacanal要变换成amanaplanacanalpanama
但是还有一个问题,比如下面这个例子
axxxxxxxxxxxxxxdyyy
由于 S S S 为 S ∗ S^* S∗ 的前缀,所以我们要找的是最长的后缀回文串
使用Manacher算法即可
代码如下
#includeusing 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; }
转载请说明出处
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)