【 HDU3294 】Girls' research (Manacher)

BUPT2017 wintertraining(15) #5F

HDU - 3294

题意

给定字母x,字符串变换一下: 'x'-1 -> 'z', ‘x’->‘a’, ‘x’+1->‘b’, ..., 求对应的字符串的最长的回文串。

题解

求最长回文串的O(n)的算法:Manacher算法

算法过程:
  1. 用’#‘号把每个字符分隔开,且开头结尾都是’#‘。
  2. RL[i]为以i为中心的最长回文最右的字符与i的距离。
  3. 已经求过的回文串中,右端点最大的回文串的中心为p。
  4. 求当前的RL[i]时,若 i 在最大右端点的左边,则RL[i] 初始值为min(RL[j],最大右端点-i),j是以p为中心,i对称的点。否则RL[i]=1。
  5. 再直接扩展RL[i],同时维护p。

代码

#include <cstdio>
#include <algorithm>
#define N 200002
using namespace std;
char c,s[N<<1];
int RL[N<<1];
int Manacher(){
    int i,p=0,q=0;
    for(i=0;s[i];i++);
    for(i;i>=0;i--) s[i*2+1]=s[i],s[i*2]='#';
    for(i=0;s[i];i++){
        if(RL[p]+p>i) RL[i]=min(RL[p*2-i],RL[p]+p-i);
        else RL[i]=1;
        while(s[i-RL[i]]&&s[i-RL[i]]==s[i+RL[i]]) RL[i]++;
        if(i+RL[i]>p+RL[p]) p=i;
        if(RL[i]>RL[q]) q=i; //q是最长的回文串的中点。
    }
    return q;
}
int main() {
    while(~scanf(" %c%s",&c,s)){
        int q=Manacher();
        int i=q-RL[q]+1,j=q+RL[q]-1;
        if(s[i]=='#')i++,j--;
        if(RL[q]>2){
            printf("%d %d\n",i/2,j/2);
            for(;i<=j;i+=2) printf("%c",(s[i]-c+26)%26+'a');
        }else printf("No solution!");
        puts("");
    }
    return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值