hdu 3068 最长回文(马拉车)

问题

hdu 3068 最长回文 - https://acm.hdu.edu.cn/showproblem.php?pid=3068

分析

  • 暴力搜索(tle)
  • 马拉车O(n)

代码

  • 暴力搜索
#include<bits/stdc++.h>
using namespace std;
const int MXN = 1e5+10;
char s[MXN];
int expand(int l, int r){ // 扩展
    while(s[l] && s[r] && s[l] == s[r]) --l, ++r;
    return r - l - 1;
}
int main(){
    int t, l, r, ans;
    scanf("%d", &t);
    while(t--){
        scanf("%s", s+1), s[0] = '\0';
        l = 1, r = 1, ans = 0;
        while(s[l] && s[r]) // 两种扩展方式的初始条件:l == r 或者 r == l+1
            ans = max(ans, expand(l, r)), l == r ? ++r : ++l;
        printf("%d\n", ans);
    }
    return 0;
}
  • Manacher(马拉车)
/* hdu 3068 最长回文 */
#include<bits/stdc++.h>
using namespace std;
const int MXN = 1.1e5+10;
char s[MXN<<1];
int R; // R是递推过程中所有出现过的对称区间的最大右边界
int p; // 与R对应的对称中心
int len[MXN<<1]; // len[i]:最大回文长度,i是回文串的对称中心(变换后的字符串)
int manacher(int n){
    int res = 0;
    for(int l, r, i = 1; i <= n; ++i){// l,r是以i为中心的对称边界
        if(i >= R) l = i, r = i; // i是对称中心,也是对称边界
        else r = min(R, i + len[(p<<1)-i]), l = (i << 1) - r;// 设定对称边界
        while(s[l-1] && s[r+1] && s[l-1] == s[r+1]) ++r, --l;// 暴力扩展
        if(r >= R) R = r, p = i; // 更新最大右边界及对称中心
        len[i] = (r - l + 1) >> 1;
        res = max(res, len[i]);
    }
    return res;
}
int main(){
    int n;
    while(scanf("%s", s+MXN) == 1){
        n = strlen(s+MXN)+1, s[0] = '\0'; // 设定一个结束符,用于扩展时比较
        for(int i = 1; i <= n; ++i) s[2*i-1] = '#', s[i<<1] = s[i+MXN-1];//变换字符串
        --n, p = 0, R = 0, len[0] = 0;
        printf("%d\n", manacher(n<<1|1));
    }
    return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

jpphy0

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值